]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #58301 - RalfJung:fat-ptr-eq, r=oli-obk
authorMazdak Farrokhzad <twingoow@gmail.com>
Thu, 14 Feb 2019 01:41:23 +0000 (02:41 +0100)
committerGitHub <noreply@github.com>
Thu, 14 Feb 2019 01:41:23 +0000 (02:41 +0100)
Enable comparing fat pointers

Also refactor our binops a bit to make that happen more easily.

r? @oli-obk

148 files changed:
src/bootstrap/builder.rs
src/bootstrap/tool.rs
src/doc/guide-error-handling.md
src/doc/guide-ownership.md
src/doc/guide-pointers.md
src/doc/guide-testing.md
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/task.rs [deleted file]
src/libcore/convert.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/future/future.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/task/mod.rs
src/libcore/task/wake.rs
src/libpanic_unwind/Cargo.toml
src/libpanic_unwind/dwarf/eh.rs
src/libpanic_unwind/emcc.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh.rs
src/libpanic_unwind/seh64_gnu.rs
src/libproc_macro/lib.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/mod.rs
src/librustc/infer/opaque_types/mod.rs
src/librustc/infer/outlives/env.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/lint/builtin.rs
src/librustc/middle/stability.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/mod.rs
src/librustc/traits/query/outlives_bounds.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/wf.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_driver/driver.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_metadata/diagnostics.rs
src/librustc_mir/diagnostics.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/error_reporting.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/spec/uefi_base.rs
src/librustc_target/spec/x86_64_unknown_uefi.rs
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_traits/normalize_projection_ty.rs
src/librustc_traits/type_op.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/structured_errors.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/librustdoc/visit_lib.rs
src/libstd/future.rs
src/libstd/lib.rs
src/libstd/panic.rs
src/libstd/prelude/mod.rs
src/libstd/sys/sgx/abi/entry.S
src/libstd/sys/sgx/abi/mod.rs
src/libstd/sys/sgx/abi/panic.rs
src/libstd/sys/sgx/abi/usercalls/mod.rs
src/libstd/sys/sgx/abi/usercalls/raw.rs
src/libstd/sys/sgx/mod.rs
src/libtest/lib.rs
src/test/compile-fail/must_use-in-stdlib-traits.rs
src/test/incremental/issue-54242.rs [new file with mode: 0644]
src/test/mir-opt/unusual-item-types.rs [new file with mode: 0644]
src/test/run-make/wasm-stringify-ints-small/Makefile [new file with mode: 0644]
src/test/run-make/wasm-stringify-ints-small/foo.rs [new file with mode: 0644]
src/test/run-pass/async-await.rs
src/test/run-pass/auxiliary/arc_wake.rs [new file with mode: 0644]
src/test/run-pass/futures-api.rs
src/test/rustdoc-js/substring.js [deleted file]
src/test/rustdoc/deprecated-future.rs
src/test/rustdoc/rustc_deprecated-future.rs [new file with mode: 0644]
src/test/ui/bad/bad-lint-cap2.stderr
src/test/ui/bad/bad-lint-cap3.stderr
src/test/ui/deprecation/deprecation-in-future.rs
src/test/ui/deprecation/deprecation-in-future.stderr
src/test/ui/deprecation/deprecation-lint.rs
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/deprecation/rustc_deprecation-in-future.rs [new file with mode: 0644]
src/test/ui/deprecation/rustc_deprecation-in-future.stderr [new file with mode: 0644]
src/test/ui/if/if-let-arm-types.rs
src/test/ui/if/if-let-arm-types.stderr
src/test/ui/imports/unused.stderr
src/test/ui/issue-42944.rs [new file with mode: 0644]
src/test/ui/issue-42944.stderr [new file with mode: 0644]
src/test/ui/issues/issue-11319.rs
src/test/ui/issues/issue-11319.stderr
src/test/ui/issues/issue-17728.rs
src/test/ui/issues/issue-17728.stderr
src/test/ui/issues/issue-24036.rs
src/test/ui/issues/issue-24036.stderr
src/test/ui/issues/issue-30730.stderr
src/test/ui/lint/lint-directives-on-use-items-issue-10534.stderr
src/test/ui/lint/lint-unused-imports.stderr
src/test/ui/lint/lints-in-foreign-macros.stderr
src/test/ui/match/match-type-err-first-arm.rs [new file with mode: 0644]
src/test/ui/match/match-type-err-first-arm.stderr [new file with mode: 0644]
src/test/ui/missing/missing-stability.rs
src/test/ui/missing/missing-stability.stderr
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/rfc-2166-underscore-imports/basic.stderr
src/test/ui/rfc-2166-underscore-imports/unused-2018.stderr
src/test/ui/span/multispan-import-lint.stderr
src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs [new file with mode: 0644]
src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-issue-43027.rs
src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr
src/test/ui/stability-attribute/stability-attribute-sanity-3.rs
src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr
src/test/ui/suggestions/as-ref.stderr
src/test/ui/use/use-nested-groups-unused-imports.stderr
src/tools/publish_toolstate.py

index 78ba1d376be79bd8e77967879bd34b13093722d6..9d037dad9ccbd15a9d88d379b59439fc39ae2da4 100644 (file)
@@ -677,10 +677,9 @@ pub fn rustdoc_cmd(&self, host: Interned<String>) -> Command {
         let compiler = self.compiler(self.top_stage, host);
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
             .env("RUSTC_SYSROOT", self.sysroot(compiler))
-            .env(
-                "RUSTDOC_LIBDIR",
-                self.sysroot_libdir(compiler, self.config.build),
-            )
+            // Note that this is *not* the sysroot_libdir because rustdoc must be linked
+            // equivalently to rustc.
+            .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
             .env("CFG_RELEASE_CHANNEL", &self.config.channel)
             .env("RUSTDOC_REAL", self.rustdoc(host))
             .env("RUSTDOC_CRATE_VERSION", self.rust_version())
@@ -874,7 +873,7 @@ pub fn cargo(
         } else {
             &maybe_sysroot
         };
-        let libdir = sysroot.join(libdir(&compiler.host));
+        let libdir = self.rustc_libdir(compiler);
 
         // Customize the compiler we're running. Specify the compiler to cargo
         // as our shim and then pass it some various options used to configure
@@ -916,7 +915,7 @@ pub fn cargo(
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
         if cmd != "build" && cmd != "check" && cmd != "rustc" && want_rustdoc {
-            cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build));
+            cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
         }
 
         if mode.is_tool() {
index c09e9332895d87f12b84671d215d6b62afc34025..6383a2ecc75832a2498fe45d66ef8c55923648f1 100644 (file)
@@ -418,25 +418,25 @@ fn make_run(run: RunConfig) {
 
     fn run(self, builder: &Builder) -> PathBuf {
         let target_compiler = builder.compiler(builder.top_stage, self.host);
+        if target_compiler.stage == 0 {
+            if !target_compiler.is_snapshot(builder) {
+                panic!("rustdoc in stage 0 must be snapshot rustdoc");
+            }
+            return builder.initial_rustc.with_file_name(exe("rustdoc", &target_compiler.host));
+        }
         let target = target_compiler.host;
-        let build_compiler = if target_compiler.stage == 0 {
-            builder.compiler(0, builder.config.build)
-        } else if target_compiler.stage >= 2 {
-            // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
-            // building rustdoc itself.
-            builder.compiler(target_compiler.stage, builder.config.build)
-        } else {
-            // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
-            // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
-            // compilers, which isn't what we want.
-            builder.compiler(target_compiler.stage - 1, builder.config.build)
-        };
-
-        builder.ensure(compile::Rustc { compiler: build_compiler, target });
-        builder.ensure(compile::Rustc {
-            compiler: build_compiler,
-            target: builder.config.build,
-        });
+        // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
+        // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
+        // compilers, which isn't what we want. Rustdoc should be linked in the same way as the
+        // rustc compiler it's paired with, so it must be built with the previous stage compiler.
+        let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
+
+        // The presence of `target_compiler` ensures that the necessary libraries (codegen backends,
+        // compiler libraries, ...) are built. Rustdoc does not require the presence of any
+        // libraries within sysroot_libdir (i.e., rustlib), though doctests may want it (since
+        // they'll be linked to those libraries). As such, don't explicitly `ensure` any additional
+        // libraries here. The intuition here is that If we've built a compiler, we should be able
+        // to build rustdoc.
 
         let mut cargo = prepare_tool_cargo(
             builder,
index 54fa529f3aa8eed2561cbfbdadfbd41b56c2cf27..fd71d3e3c8e79e1030039dc17f587cda6018df3a 100644 (file)
@@ -1,4 +1,4 @@
 % Error Handling in Rust
 
 This content has moved into
-[the Rust Programming Language book](book/error-handling.html).
+[the Rust Programming Language book](book/ch09-00-error-handling.html).
index 884f14726ca87e7b7c75137cbfa942acc6873b43..767dafc5baf9208e3927680947fe3da83c493201 100644 (file)
@@ -1,4 +1,4 @@
 % The (old) Rust Ownership Guide
 
 This content has moved into
-[the Rust Programming Language book](book/ownership.html).
+[the Rust Programming Language book](book/ch04-00-understanding-ownership.html).
index dc80ec4399131470dab2876cadd8cf09ad8bd577..bafdb2fe0bbc3790867d1e8a117226f033c298ae 100644 (file)
@@ -2,6 +2,6 @@
 
 This content has been removed, with no direct replacement. Rust only
 has two built-in pointer types now,
-[references](book/references-and-borrowing.html) and [raw
+[references](book/ch04-02-references-and-borrowing.html) and [raw
 pointers](book/raw-pointers.html). Older Rusts had many more pointer
 types, they’re gone now.
index 67bcb0a5e546a950016498783845eb4372f4644d..28d9fb48b73e74485f6a8b930428a7fbb6db81ef 100644 (file)
@@ -1,4 +1,4 @@
 % The (old) Rust Testing Guide
 
 This content has moved into
-[the Rust Programming Language book](book/testing.html).
+[the Rust Programming Language book](book/ch11-00-testing.html).
index 8e01e12e0b8def3106d164e2faa2f8233eaf0e49..51549f92d4dbf02e50a2a48c21ff8339988c2e3b 100644 (file)
@@ -71,7 +71,7 @@
     CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
 };
 use core::ptr::{self, NonNull, Unique};
-use core::task::{LocalWaker, Poll};
+use core::task::{Waker, Poll};
 
 use crate::vec::Vec;
 use crate::raw_vec::RawVec;
@@ -896,7 +896,7 @@ fn resume(mut self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>
 impl<F: ?Sized + Future + Unpin> Future for Box<F> {
     type Output = F::Output;
 
-    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
-        F::poll(Pin::new(&mut *self), lw)
+    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut *self), waker)
     }
 }
index d4ee428a3b5c775ee4369d004d9707a2b4902932..95b9dacf8565aa5ea9357e26bded9031129ac3d6 100644 (file)
 
 pub mod alloc;
 
-#[unstable(feature = "futures_api",
-           reason = "futures in libcore are unstable",
-           issue = "50547")]
-pub mod task;
 // Primitive types using the heaps above
 
 // Need to conditionally define the mod from `boxed.rs` to avoid
diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs
deleted file mode 100644 (file)
index 2261dab..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-//! Types and Traits for working with asynchronous tasks.
-
-pub use core::task::*;
-
-#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
-pub use if_arc::*;
-
-#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
-mod if_arc {
-    use super::*;
-    use core::marker::PhantomData;
-    use core::mem;
-    use core::ptr::{self, NonNull};
-    use crate::sync::Arc;
-
-    /// A way of waking up a specific task.
-    ///
-    /// Any task executor must provide a way of signaling that a task it owns
-    /// is ready to be `poll`ed again. Executors do so by implementing this trait.
-    pub trait Wake: Send + Sync {
-        /// Indicates that the associated task is ready to make progress and should
-        /// be `poll`ed.
-        ///
-        /// Executors generally maintain a queue of "ready" tasks; `wake` should place
-        /// the associated task onto this queue.
-        fn wake(arc_self: &Arc<Self>);
-
-        /// Indicates that the associated task is ready to make progress and should
-        /// be `poll`ed. This function is like `wake`, but can only be called from the
-        /// thread on which this `Wake` was created.
-        ///
-        /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
-        /// the associated task onto this queue.
-        #[inline]
-        unsafe fn wake_local(arc_self: &Arc<Self>) {
-            Self::wake(arc_self);
-        }
-    }
-
-    #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
-    struct ArcWrapped<T>(PhantomData<T>);
-
-    unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
-        #[inline]
-        unsafe fn clone_raw(&self) -> Waker {
-            let me: *const ArcWrapped<T> = self;
-            let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
-            Waker::from(arc)
-        }
-
-        #[inline]
-        unsafe fn drop_raw(&self) {
-            let mut me: *const ArcWrapped<T> = self;
-            let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
-            ptr::drop_in_place(me);
-        }
-
-        #[inline]
-        unsafe fn wake(&self) {
-            let me: *const ArcWrapped<T> = self;
-            T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
-        }
-
-        #[inline]
-        unsafe fn wake_local(&self) {
-            let me: *const ArcWrapped<T> = self;
-            T::wake_local(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
-        }
-    }
-
-    impl<T> From<Arc<T>> for Waker
-        where T: Wake + 'static,
-    {
-        fn from(rc: Arc<T>) -> Self {
-            unsafe {
-                let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
-                Waker::new(ptr)
-            }
-        }
-    }
-
-    /// Creates a `LocalWaker` from a local `wake`.
-    ///
-    /// This function requires that `wake` is "local" (created on the current thread).
-    /// The resulting `LocalWaker` will call `wake.wake_local()` when awoken, and
-    /// will call `wake.wake()` if awoken after being converted to a `Waker`.
-    #[inline]
-    pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
-        let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
-        LocalWaker::new(ptr)
-    }
-
-    struct NonLocalAsLocal<T>(ArcWrapped<T>);
-
-    unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
-        #[inline]
-        unsafe fn clone_raw(&self) -> Waker {
-            self.0.clone_raw()
-        }
-
-        #[inline]
-        unsafe fn drop_raw(&self) {
-            self.0.drop_raw()
-        }
-
-        #[inline]
-        unsafe fn wake(&self) {
-            self.0.wake()
-        }
-
-        #[inline]
-        unsafe fn wake_local(&self) {
-            // Since we're nonlocal, we can't call wake_local
-            self.0.wake()
-        }
-    }
-
-    /// Creates a `LocalWaker` from a non-local `wake`.
-    ///
-    /// This function is similar to `local_waker`, but does not require that `wake`
-    /// is local to the current thread. The resulting `LocalWaker` will call
-    /// `wake.wake()` when awoken.
-    #[inline]
-    pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
-        unsafe {
-            let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);
-            LocalWaker::new(ptr)
-        }
-    }
-}
index 4a7c6e15a4df1bf947384c8304ffc2cc290feb54..b8d751cfbb6df24f06b8d5e8dd0ed9fb33210436 100644 (file)
@@ -116,9 +116,6 @@ pub const fn identity<T>(x: T) -> T { x }
 /// - Use `Borrow` when the goal is related to writing code that is agnostic to
 ///   the type of borrow and whether it is a reference or value
 ///
-/// See [the book][book] for a more detailed comparison.
-///
-/// [book]: ../../book/first-edition/borrow-and-asref.html
 /// [`Borrow`]: ../../std/borrow/trait.Borrow.html
 ///
 /// **Note: this trait must not fail**. If the conversion can fail, use a
@@ -351,7 +348,7 @@ pub trait Into<T>: Sized {
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Into<U>`]: trait.Into.html
 /// [`from`]: trait.From.html#tymethod.from
-/// [book]: ../../book/first-edition/error-handling.html
+/// [book]: ../../book/ch09-00-error-handling.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait From<T>: Sized {
     /// Performs the conversion.
index 2ce58c803b878ec2b153d063183b130fbe86b1e5..7efb7f31298bf194fea3657d7555519e26a04a46 100644 (file)
@@ -1036,6 +1036,27 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result {
     Ok(())
 }
 
+/// Padding after the end of something. Returned by `Formatter::padding`.
+#[must_use = "don't forget to write the post padding"]
+struct PostPadding {
+    fill: char,
+    padding: usize,
+}
+
+impl PostPadding {
+    fn new(fill: char, padding: usize) -> PostPadding {
+        PostPadding { fill, padding }
+    }
+
+    /// Write this post padding.
+    fn write(self, buf: &mut dyn Write) -> Result {
+        for _ in 0..self.padding {
+            buf.write_char(self.fill)?;
+        }
+        Ok(())
+    }
+}
+
 impl<'a> Formatter<'a> {
     fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>
         where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c)
@@ -1153,47 +1174,56 @@ pub fn pad_integral(&mut self,
             sign = Some('+'); width += 1;
         }
 
-        let prefixed = self.alternate();
-        if prefixed {
+        let prefix = if self.alternate() {
             width += prefix.chars().count();
-        }
+            Some(prefix)
+        } else {
+            None
+        };
 
         // Writes the sign if it exists, and then the prefix if it was requested
-        let write_prefix = |f: &mut Formatter| {
+        #[inline(never)]
+        fn write_prefix(f: &mut Formatter, sign: Option<char>, prefix: Option<&str>) -> Result {
             if let Some(c) = sign {
                 f.buf.write_char(c)?;
             }
-            if prefixed { f.buf.write_str(prefix) }
-            else { Ok(()) }
-        };
+            if let Some(prefix) = prefix {
+                f.buf.write_str(prefix)
+            } else {
+                Ok(())
+            }
+        }
 
         // The `width` field is more of a `min-width` parameter at this point.
         match self.width {
             // If there's no minimum length requirements then we can just
             // write the bytes.
             None => {
-                write_prefix(self)?; self.buf.write_str(buf)
+                write_prefix(self, sign, prefix)?;
+                self.buf.write_str(buf)
             }
             // Check if we're over the minimum width, if so then we can also
             // just write the bytes.
             Some(min) if width >= min => {
-                write_prefix(self)?; self.buf.write_str(buf)
+                write_prefix(self, sign, prefix)?;
+                self.buf.write_str(buf)
             }
             // The sign and prefix goes before the padding if the fill character
             // is zero
             Some(min) if self.sign_aware_zero_pad() => {
                 self.fill = '0';
                 self.align = rt::v1::Alignment::Right;
-                write_prefix(self)?;
-                self.with_padding(min - width, rt::v1::Alignment::Right, |f| {
-                    f.buf.write_str(buf)
-                })
+                write_prefix(self, sign, prefix)?;
+                let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
+                self.buf.write_str(buf)?;
+                post_padding.write(self.buf)
             }
             // Otherwise, the sign and prefix goes after the padding
             Some(min) => {
-                self.with_padding(min - width, rt::v1::Alignment::Right, |f| {
-                    write_prefix(f)?; f.buf.write_str(buf)
-                })
+                let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
+                write_prefix(self, sign, prefix)?;
+                self.buf.write_str(buf)?;
+                post_padding.write(self.buf)
             }
         }
     }
@@ -1264,19 +1294,21 @@ pub fn pad(&mut self, s: &str) -> Result {
             // up the minimum width with the specified string + some alignment.
             Some(width) => {
                 let align = rt::v1::Alignment::Left;
-                self.with_padding(width - s.chars().count(), align, |me| {
-                    me.buf.write_str(s)
-                })
+                let post_padding = self.padding(width - s.chars().count(), align)?;
+                self.buf.write_str(s)?;
+                post_padding.write(self.buf)
             }
         }
     }
 
-    /// Runs a callback, emitting the correct padding either before or
-    /// afterwards depending on whether right or left alignment is requested.
-    fn with_padding<F>(&mut self, padding: usize, default: rt::v1::Alignment,
-                       f: F) -> Result
-        where F: FnOnce(&mut Formatter) -> Result,
-    {
+    /// Write the pre-padding and return the unwritten post-padding. Callers are
+    /// responsible for ensuring post-padding is written after the thing that is
+    /// being padded.
+    fn padding(
+        &mut self,
+        padding: usize,
+        default: rt::v1::Alignment
+    ) -> result::Result<PostPadding, Error> {
         let align = match self.align {
             rt::v1::Alignment::Unknown => default,
             _ => self.align
@@ -1289,20 +1321,11 @@ fn with_padding<F>(&mut self, padding: usize, default: rt::v1::Alignment,
             rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2),
         };
 
-        let mut fill = [0; 4];
-        let fill = self.fill.encode_utf8(&mut fill);
-
         for _ in 0..pre_pad {
-            self.buf.write_str(fill)?;
-        }
-
-        f(self)?;
-
-        for _ in 0..post_pad {
-            self.buf.write_str(fill)?;
+            self.buf.write_char(self.fill)?;
         }
 
-        Ok(())
+        Ok(PostPadding::new(self.fill, post_pad))
     }
 
     /// Takes the formatted parts and applies the padding.
@@ -1334,9 +1357,9 @@ fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted) -> Result {
             let ret = if width <= len { // no padding
                 self.write_formatted_parts(&formatted)
             } else {
-                self.with_padding(width - len, align, |f| {
-                    f.write_formatted_parts(&formatted)
-                })
+                let post_padding = self.padding(width - len, align)?;
+                self.write_formatted_parts(&formatted)?;
+                post_padding.write(self.buf)
             };
             self.fill = old_fill;
             self.align = old_align;
index 3a812337bb111e855f6053cb8c0088ae89f5f528..b9fa3640371082148624f625ad1e0eabbea9faa7 100644 (file)
@@ -178,7 +178,8 @@ macro_rules! integer {
 integer! { i64, u64 }
 integer! { i128, u128 }
 
-const DEC_DIGITS_LUT: &'static[u8] =
+
+static DEC_DIGITS_LUT: &[u8; 200] =
     b"0001020304050607080910111213141516171819\
       2021222324252627282930313233343536373839\
       4041424344454647484950515253545556575859\
@@ -186,18 +187,8 @@ macro_rules! integer {
       8081828384858687888990919293949596979899";
 
 macro_rules! impl_Display {
-    ($($t:ident),*: $conv_fn:ident) => ($(
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl fmt::Display for $t {
-        #[allow(unused_comparisons)]
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            let is_nonnegative = *self >= 0;
-            let mut n = if is_nonnegative {
-                self.$conv_fn()
-            } else {
-                // convert the negative num to positive by summing 1 to it's 2 complement
-                (!self.$conv_fn()).wrapping_add(1)
-            };
+    ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
+        fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter) -> fmt::Result {
             let mut buf = uninitialized_array![u8; 39];
             let mut curr = buf.len() as isize;
             let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf);
@@ -205,18 +196,18 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
             unsafe {
                 // need at least 16 bits for the 4-characters-at-a-time to work.
-                if ::mem::size_of::<$t>() >= 2 {
-                    // eagerly decode 4 characters at a time
-                    while n >= 10000 {
-                        let rem = (n % 10000) as isize;
-                        n /= 10000;
-
-                        let d1 = (rem / 100) << 1;
-                        let d2 = (rem % 100) << 1;
-                        curr -= 4;
-                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
-                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
-                    }
+                assert!(::mem::size_of::<$u>() >= 2);
+
+                // eagerly decode 4 characters at a time
+                while n >= 10000 {
+                    let rem = (n % 10000) as isize;
+                    n /= 10000;
+
+                    let d1 = (rem / 100) << 1;
+                    let d2 = (rem % 100) << 1;
+                    curr -= 4;
+                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+                    ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                 }
 
                 // if we reach here numbers are <= 9999, so at most 4 chars long
@@ -247,15 +238,41 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             };
             f.pad_integral(is_nonnegative, "", buf_slice)
         }
-    })*);
+
+        $(
+            #[stable(feature = "rust1", since = "1.0.0")]
+            impl fmt::Display for $t {
+                #[allow(unused_comparisons)]
+                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    let is_nonnegative = *self >= 0;
+                    let n = if is_nonnegative {
+                        self.$conv_fn()
+                    } else {
+                        // convert the negative num to positive by summing 1 to it's 2 complement
+                        (!self.$conv_fn()).wrapping_add(1)
+                    };
+                    $name(n, is_nonnegative, f)
+                }
+            })*
+    };
+}
+
+// Include wasm32 in here since it doesn't reflect the native pointer size, and
+// often cares strongly about getting a smaller code size.
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+mod imp {
+    use super::*;
+    impl_Display!(
+        i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
+            as u64 via to_u64 named fmt_u64
+    );
+}
+
+#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
+mod imp {
+    use super::*;
+    impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
+    impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
 }
 
-impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
-impl_Display!(i64, u64: to_u64);
-impl_Display!(i128, u128: to_u128);
-#[cfg(target_pointer_width = "16")]
-impl_Display!(isize, usize: to_u16);
-#[cfg(target_pointer_width = "32")]
-impl_Display!(isize, usize: to_u32);
-#[cfg(target_pointer_width = "64")]
-impl_Display!(isize, usize: to_u64);
+impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128);
index 0f142347a95babd3f429f459b1c78893d0805579..02457e00054c8eb0f19f8d95a1d9a2300f53f942 100644 (file)
@@ -5,7 +5,7 @@
 use marker::Unpin;
 use ops;
 use pin::Pin;
-use task::{Poll, LocalWaker};
+use task::{Poll, Waker};
 
 /// A future represents an asynchronous computation.
 ///
 /// final value. This method does not block if the value is not ready. Instead,
 /// the current task is scheduled to be woken up when it's possible to make
 /// further progress by `poll`ing again. The wake up is performed using
-/// `cx.waker()`, a handle for waking up the current task.
+/// the `waker` argument of the `poll()` method, which is a handle for waking
+/// up the current task.
 ///
 /// When using a future, you generally won't call `poll` directly, but instead
 /// `await!` the value.
 #[must_use = "futures do nothing unless polled"]
 pub trait Future {
-    /// The result of the `Future`.
+    /// The type of value produced on completion.
     type Output;
 
     /// Attempt to resolve the future to a final value, registering
@@ -42,16 +43,16 @@ pub trait Future {
     /// Once a future has finished, clients should not `poll` it again.
     ///
     /// When a future is not ready yet, `poll` returns `Poll::Pending` and
-    /// stores a clone of the [`LocalWaker`] to be woken once the future can
+    /// stores a clone of the [`Waker`] to be woken once the future can
     /// make progress. For example, a future waiting for a socket to become
-    /// readable would call `.clone()` on the [`LocalWaker`] and store it.
+    /// readable would call `.clone()` on the [`Waker`] and store it.
     /// When a signal arrives elsewhere indicating that the socket is readable,
-    /// `[LocalWaker::wake]` is called and the socket future's task is awoken.
+    /// `[Waker::wake]` is called and the socket future's task is awoken.
     /// Once a task has been woken up, it should attempt to `poll` the future
     /// again, which may or may not produce a final value.
     ///
     /// Note that on multiple calls to `poll`, only the most recent
-    /// [`LocalWaker`] passed to `poll` should be scheduled to receive a
+    /// [`Waker`] passed to `poll` should be scheduled to receive a
     /// wakeup.
     ///
     /// # Runtime characteristics
@@ -67,44 +68,35 @@ pub trait Future {
     /// typically do *not* suffer the same problems of "all wakeups must poll
     /// all events"; they are more like `epoll(4)`.
     ///
-    /// An implementation of `poll` should strive to return quickly, and must
-    /// *never* block. Returning quickly prevents unnecessarily clogging up
+    /// An implementation of `poll` should strive to return quickly, and should
+    /// not block. Returning quickly prevents unnecessarily clogging up
     /// threads or event loops. If it is known ahead of time that a call to
     /// `poll` may end up taking awhile, the work should be offloaded to a
     /// thread pool (or something similar) to ensure that `poll` can return
     /// quickly.
     ///
-    /// # [`LocalWaker`], [`Waker`] and thread-safety
-    ///
-    /// The `poll` function takes a [`LocalWaker`], an object which knows how to
-    /// awaken the current task. [`LocalWaker`] is not `Send` nor `Sync`, so in
-    /// order to make thread-safe futures the [`LocalWaker::into_waker`] method
-    /// should be used to convert the [`LocalWaker`] into a thread-safe version.
-    /// [`LocalWaker::wake`] implementations have the ability to be more
-    /// efficient, however, so when thread safety is not necessary,
-    /// [`LocalWaker`] should be preferred.
+    /// An implementation of `poll` may also never cause memory unsafety.
     ///
     /// # Panics
     ///
     /// Once a future has completed (returned `Ready` from `poll`),
     /// then any future calls to `poll` may panic, block forever, or otherwise
-    /// cause bad behavior. The `Future` trait itself provides no guarantees
-    /// about the behavior of `poll` after a future has completed.
+    /// cause any kind of bad behavior expect causing memory unsafety.
+    /// The `Future` trait itself provides no guarantees about the behavior
+    /// of `poll` after a future has completed.
     ///
     /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
     /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
-    /// [`LocalWaker`]: ../task/struct.LocalWaker.html
-    /// [`LocalWaker::into_waker`]: ../task/struct.LocalWaker.html#method.into_waker
-    /// [`LocalWaker::wake`]: ../task/struct.LocalWaker.html#method.wake
     /// [`Waker`]: ../task/struct.Waker.html
-    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output>;
+    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
+    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output>;
 }
 
 impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
     type Output = F::Output;
 
-    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
-        F::poll(Pin::new(&mut **self), lw)
+    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+        F::poll(Pin::new(&mut **self), waker)
     }
 }
 
@@ -115,7 +107,7 @@ impl<P> Future for Pin<P>
 {
     type Output = <<P as ops::Deref>::Target as Future>::Output;
 
-    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
-        Pin::get_mut(self).as_mut().poll(lw)
+    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+        Pin::get_mut(self).as_mut().poll(waker)
     }
 }
index 457d556e4fa6d2db6fbc33233ded1bbe5a3c838d..c4b41f1a3090c3685e52a228a6b9efbf1ebb9836 100644 (file)
@@ -78,7 +78,7 @@ impl<T: ?Sized> !Send for *mut T { }
 ///                         // be made into an object
 /// ```
 ///
-/// [trait object]: ../../book/first-edition/trait-objects.html
+/// [trait object]: ../../book/ch17-02-trait-objects.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sized"]
 #[rustc_on_unimplemented(
@@ -518,7 +518,7 @@ fn default() -> $t<T> {
 /// types. We track the Rust type using a phantom type parameter on
 /// the struct `ExternalResource` which wraps a handle.
 ///
-/// [FFI]: ../../book/first-edition/ffi.html
+/// [FFI]: ../../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
 ///
 /// ```
 /// # #![allow(dead_code)]
index 2a493e88fe89617ccdb0121fb42befc58e5848a5..3f7455aeb59b9bcfef22fabdb5f9b4c7cb0c2351 100644 (file)
@@ -299,7 +299,7 @@ pub const fn size_of<T>() -> usize {
 /// then `size_of_val` can be used to get the dynamically-known size.
 ///
 /// [slice]: ../../std/primitive.slice.html
-/// [trait object]: ../../book/first-edition/trait-objects.html
+/// [trait object]: ../../book/ch17-02-trait-objects.html
 ///
 /// # Examples
 ///
index 9552e53ebf8493da26066157a797a08412889235..9b8f59811620083edf04be7e8cb1b8795d2d1253 100644 (file)
@@ -8,4 +8,4 @@
 pub use self::poll::Poll;
 
 mod wake;
-pub use self::wake::{Waker, LocalWaker, UnsafeWake};
+pub use self::wake::{Waker, RawWaker, RawWakerVTable};
index 6d54989706cac9c46c2a1282c299d84fdb449bf3..21f0a8cea4168a87667a3aa571545aa92091a4d5 100644 (file)
@@ -4,16 +4,92 @@
 
 use fmt;
 use marker::Unpin;
-use ptr::NonNull;
+
+/// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
+/// which provides customized wakeup behavior.
+///
+/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table
+///
+/// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that
+/// customizes the behavior of the `RawWaker`.
+#[derive(PartialEq, Debug)]
+pub struct RawWaker {
+    /// A data pointer, which can be used to store arbitrary data as required
+    /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
+    /// that is associated with the task.
+    /// The value of this field gets passed to all functions that are part of
+    /// the vtable as the first parameter.
+    data: *const (),
+    /// Virtual function pointer table that customizes the behavior of this waker.
+    vtable: &'static RawWakerVTable,
+}
+
+impl RawWaker {
+    /// Creates a new `RawWaker` from the provided `data` pointer and `vtable`.
+    ///
+    /// The `data` pointer can be used to store arbitrary data as required
+    /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
+    /// that is associated with the task.
+    /// The value of this poiner will get passed to all functions that are part
+    /// of the `vtable` as the first parameter.
+    ///
+    /// The `vtable` customizes the behavior of a `Waker` which gets created
+    /// from a `RawWaker`. For each operation on the `Waker`, the associated
+    /// function in the `vtable` of the underlying `RawWaker` will be called.
+    pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
+        RawWaker {
+            data,
+            vtable,
+        }
+    }
+}
+
+/// A virtual function pointer table (vtable) that specifies the behavior
+/// of a [`RawWaker`].
+///
+/// The pointer passed to all functions inside the vtable is the `data` pointer
+/// from the enclosing [`RawWaker`] object.
+///
+/// The functions inside this struct are only intended be called on the `data`
+/// pointer of a properly constructed [`RawWaker`] object from inside the
+/// [`RawWaker`] implementation. Calling one of the contained functions using
+/// any other `data` pointer will cause undefined behavior.
+#[derive(PartialEq, Copy, Clone, Debug)]
+pub struct RawWakerVTable {
+    /// This function will be called when the [`RawWaker`] gets cloned, e.g. when
+    /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned.
+    ///
+    /// The implementation of this function must retain all resources that are
+    /// required for this additional instance of a [`RawWaker`] and associated
+    /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
+    /// of the same task that would have been awoken by the original [`RawWaker`].
+    pub clone: unsafe fn(*const ()) -> RawWaker,
+
+    /// This function will be called when `wake` is called on the [`Waker`].
+    /// It must wake up the task associated with this [`RawWaker`].
+    ///
+    /// The implemention of this function must not consume the provided data
+    /// pointer.
+    pub wake: unsafe fn(*const ()),
+
+    /// This function gets called when a [`RawWaker`] gets dropped.
+    ///
+    /// The implementation of this function must make sure to release any
+    /// resources that are associated with this instance of a [`RawWaker`] and
+    /// associated task.
+    pub drop: unsafe fn(*const ()),
+}
 
 /// A `Waker` is a handle for waking up a task by notifying its executor that it
 /// is ready to be run.
 ///
-/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
-/// trait, allowing notifications to get routed through it.
+/// This handle encapsulates a [`RawWaker`] instance, which defines the
+/// executor-specific wakeup behavior.
+///
+/// Implements [`Clone`], [`Send`], and [`Sync`].
 #[repr(transparent)]
 pub struct Waker {
-    inner: NonNull<dyn UnsafeWake>,
+    waker: RawWaker,
 }
 
 impl Unpin for Waker {}
@@ -21,264 +97,66 @@ unsafe impl Send for Waker {}
 unsafe impl Sync for Waker {}
 
 impl Waker {
-    /// Constructs a new `Waker` directly.
-    ///
-    /// Note that most code will not need to call this. Implementers of the
-    /// `UnsafeWake` trait will typically provide a wrapper that calls this
-    /// but you otherwise shouldn't call it directly.
-    ///
-    /// If you're working with the standard library then it's recommended to
-    /// use the `Waker::from` function instead which works with the safe
-    /// `Arc` type and the safe `Wake` trait.
-    #[inline]
-    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
-        Waker { inner }
-    }
-
     /// Wake up the task associated with this `Waker`.
-    #[inline]
     pub fn wake(&self) {
-        unsafe { self.inner.as_ref().wake() }
+        // The actual wakeup call is delegated through a virtual function call
+        // to the implementation which is defined by the executor.
+
+        // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+        // to initialize `wake` and `data` requiring the user to acknowledge
+        // that the contract of `RawWaker` is upheld.
+        unsafe { (self.waker.vtable.wake)(self.waker.data) }
     }
 
-    /// Returns `true` if or not this `Waker` and `other` awaken the same task.
+    /// Returns whether or not this `Waker` and other `Waker` have awaken the same task.
     ///
     /// This function works on a best-effort basis, and may return false even
     /// when the `Waker`s would awaken the same task. However, if this function
-    /// returns `true`, it is guaranteed that the `Waker`s will awaken the same
-    /// task.
+    /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
     ///
     /// This function is primarily used for optimization purposes.
-    #[inline]
     pub fn will_wake(&self, other: &Waker) -> bool {
-        self.inner == other.inner
+        self.waker == other.waker
     }
 
-    /// Returns `true` if or not this `Waker` and `other` `LocalWaker` awaken
-    /// the same task.
+    /// Creates a new `Waker` from [`RawWaker`].
     ///
-    /// This function works on a best-effort basis, and may return false even
-    /// when the `Waker`s would awaken the same task. However, if this function
-    /// returns true, it is guaranteed that the `Waker`s will awaken the same
-    /// task.
-    ///
-    /// This function is primarily used for optimization purposes.
-    #[inline]
-    pub fn will_wake_local(&self, other: &LocalWaker) -> bool {
-        self.will_wake(&other.0)
+    /// The behavior of the returned `Waker` is undefined if the contract defined
+    /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
+    /// Therefore this method is unsafe.
+    pub unsafe fn new_unchecked(waker: RawWaker) -> Waker {
+        Waker {
+            waker,
+        }
     }
 }
 
 impl Clone for Waker {
-    #[inline]
     fn clone(&self) -> Self {
-        unsafe {
-            self.inner.as_ref().clone_raw()
+        Waker {
+            // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+            // to initialize `clone` and `data` requiring the user to acknowledge
+            // that the contract of [`RawWaker`] is upheld.
+            waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
         }
     }
 }
 
-impl fmt::Debug for Waker {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Waker")
-            .finish()
-    }
-}
-
 impl Drop for Waker {
-    #[inline]
     fn drop(&mut self) {
-        unsafe {
-            self.inner.as_ref().drop_raw()
-        }
-    }
-}
-
-/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
-/// is ready to be run.
-///
-/// This is similar to the `Waker` type, but cannot be sent across threads.
-/// Task executors can use this type to implement more optimized single-threaded wakeup
-/// behavior.
-#[repr(transparent)]
-#[derive(Clone)]
-pub struct LocalWaker(Waker);
-
-impl Unpin for LocalWaker {}
-impl !Send for LocalWaker {}
-impl !Sync for LocalWaker {}
-
-impl LocalWaker {
-    /// Constructs a new `LocalWaker` directly.
-    ///
-    /// Note that most code will not need to call this. Implementers of the
-    /// `UnsafeWake` trait will typically provide a wrapper that calls this
-    /// but you otherwise shouldn't call it directly.
-    ///
-    /// If you're working with the standard library then it's recommended to
-    /// use the `local_waker_from_nonlocal` or `local_waker` to convert a `Waker`
-    /// into a `LocalWaker`.
-    ///
-    /// For this function to be used safely, it must be sound to call `inner.wake_local()`
-    /// on the current thread.
-    #[inline]
-    pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
-        LocalWaker(Waker::new(inner))
-    }
-
-    /// Borrows this `LocalWaker` as a `Waker`.
-    ///
-    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
-    /// (implements `Send` and `Sync`).
-    #[inline]
-    pub fn as_waker(&self) -> &Waker {
-        &self.0
-    }
-
-    /// Converts this `LocalWaker` into a `Waker`.
-    ///
-    /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe
-    /// (implements `Send` and `Sync`).
-    #[inline]
-    pub fn into_waker(self) -> Waker {
-        self.0
-    }
-
-    /// Wake up the task associated with this `LocalWaker`.
-    #[inline]
-    pub fn wake(&self) {
-        unsafe { self.0.inner.as_ref().wake_local() }
-    }
-
-    /// Returns `true` if or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
-    ///
-    /// This function works on a best-effort basis, and may return false even
-    /// when the `LocalWaker`s would awaken the same task. However, if this function
-    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
-    /// task.
-    ///
-    /// This function is primarily used for optimization purposes.
-    #[inline]
-    pub fn will_wake(&self, other: &LocalWaker) -> bool {
-        self.0.will_wake(&other.0)
-    }
-
-    /// Returns `true` if or not this `LocalWaker` and `other` `Waker` awaken the same task.
-    ///
-    /// This function works on a best-effort basis, and may return false even
-    /// when the `Waker`s would awaken the same task. However, if this function
-    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
-    /// task.
-    ///
-    /// This function is primarily used for optimization purposes.
-    #[inline]
-    pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
-        self.0.will_wake(other)
-    }
-}
-
-impl From<LocalWaker> for Waker {
-    /// Converts a `LocalWaker` into a `Waker`.
-    ///
-    /// This conversion turns a `!Sync` `LocalWaker` into a `Sync` `Waker`, allowing a wakeup
-    /// object to be sent to another thread, but giving up its ability to do specialized
-    /// thread-local wakeup behavior.
-    #[inline]
-    fn from(local_waker: LocalWaker) -> Self {
-        local_waker.0
+        // SAFETY: This is safe because `Waker::new_unchecked` is the only way
+        // to initialize `drop` and `data` requiring the user to acknowledge
+        // that the contract of `RawWaker` is upheld.
+        unsafe { (self.waker.vtable.drop)(self.waker.data) }
     }
 }
 
-impl fmt::Debug for LocalWaker {
+impl fmt::Debug for Waker {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("LocalWaker")
+        let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
+        f.debug_struct("Waker")
+            .field("data", &self.waker.data)
+            .field("vtable", &vtable_ptr)
             .finish()
     }
 }
-
-/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
-///
-/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
-/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
-/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
-/// custom memory management strategy. This trait is designed to allow for such
-/// customization.
-///
-/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
-/// `Arc<T>` where `T: Wake`.
-pub unsafe trait UnsafeWake: Send + Sync {
-    /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
-    ///
-    /// This function will create a new uniquely owned handle that under the
-    /// hood references the same notification instance. In other words calls
-    /// to `wake` on the returned handle should be equivalent to calls to
-    /// `wake` on this handle.
-    ///
-    /// # Unsafety
-    ///
-    /// This function is unsafe to call because it's asserting the `UnsafeWake`
-    /// value is in a consistent state, i.e., hasn't been dropped.
-    unsafe fn clone_raw(&self) -> Waker;
-
-    /// Drops this instance of `UnsafeWake`, deallocating resources
-    /// associated with it.
-    ///
-    // FIXME(cramertj):
-    /// This method is intended to have a signature such as:
-    ///
-    /// ```ignore (not-a-doctest)
-    /// fn drop_raw(self: *mut Self);
-    /// ```
-    ///
-    /// Unfortunately, in Rust today that signature is not object safe.
-    /// Nevertheless it's recommended to implement this function *as if* that
-    /// were its signature. As such it is not safe to call on an invalid
-    /// pointer, nor is the validity of the pointer guaranteed after this
-    /// function returns.
-    ///
-    /// # Unsafety
-    ///
-    /// This function is unsafe to call because it's asserting the `UnsafeWake`
-    /// value is in a consistent state, i.e., hasn't been dropped.
-    unsafe fn drop_raw(&self);
-
-    /// Indicates that the associated task is ready to make progress and should
-    /// be `poll`ed.
-    ///
-    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
-    /// the associated task onto this queue.
-    ///
-    /// # Panics
-    ///
-    /// Implementations should avoid panicking, but clients should also be prepared
-    /// for panics.
-    ///
-    /// # Unsafety
-    ///
-    /// This function is unsafe to call because it's asserting the `UnsafeWake`
-    /// value is in a consistent state, i.e., hasn't been dropped.
-    unsafe fn wake(&self);
-
-    /// Indicates that the associated task is ready to make progress and should
-    /// be `poll`ed. This function is the same as `wake`, but can only be called
-    /// from the thread that this `UnsafeWake` is "local" to. This allows for
-    /// implementors to provide specialized wakeup behavior specific to the current
-    /// thread. This function is called by `LocalWaker::wake`.
-    ///
-    /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
-    /// the associated task onto this queue.
-    ///
-    /// # Panics
-    ///
-    /// Implementations should avoid panicking, but clients should also be prepared
-    /// for panics.
-    ///
-    /// # Unsafety
-    ///
-    /// This function is unsafe to call because it's asserting the `UnsafeWake`
-    /// value is in a consistent state, i.e., hasn't been dropped, and that the
-    /// `UnsafeWake` hasn't moved from the thread on which it was created.
-    unsafe fn wake_local(&self) {
-        self.wake()
-    }
-}
index c9fce621608a24cb8155f2a2d6256434b8459292..1b3901ac11a96c580c605497a3a074c2fe58c50d 100644 (file)
@@ -2,6 +2,7 @@
 authors = ["The Rust Project Developers"]
 name = "panic_unwind"
 version = "0.0.0"
+edition = "2018"
 
 [lib]
 path = "lib.rs"
index ce24406b556420af262f0b33198014ad95367132..07fa2971847f65d5d49df89a547e3b6c8ca86d75 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(non_upper_case_globals)]
 #![allow(unused)]
 
-use dwarf::DwarfReader;
+use crate::dwarf::DwarfReader;
 use core::mem;
 
 pub const DW_EH_PE_omit: u8 = 0xFF;
@@ -51,7 +51,7 @@ pub enum EHAction {
 
 pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
 
-pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext)
+pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>)
     -> Result<EHAction, ()>
 {
     if lsda.is_null() {
@@ -145,7 +145,7 @@ fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
 }
 
 unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
-                               context: &EHContext,
+                               context: &EHContext<'_>,
                                encoding: u8)
                                -> Result<usize, ()> {
     if encoding == DW_EH_PE_omit {
index 1f5ccfb0f121032070fb484dff5150b82e90bcca..18e9006468ef3500c6b7f4de3d79d2a440673013 100644 (file)
 
 use core::any::Any;
 use core::ptr;
+use core::mem;
 use alloc::boxed::Box;
 use libc::{self, c_int};
 use unwind as uw;
-use core::mem;
 
 pub fn payload() -> *mut u8 {
     ptr::null_mut()
index 607fe28e3f28de7021de6bded40a5825be2f25f1..e2b743b379704b5faf18c1d96c14b6aae9a00f72 100644 (file)
@@ -52,7 +52,7 @@
 
 use unwind as uw;
 use libc::{c_int, uintptr_t};
-use dwarf::eh::{self, EHContext, EHAction};
+use crate::dwarf::eh::{self, EHContext, EHAction};
 
 #[repr(C)]
 struct Exception {
index fa7a0916d429bc10074a55f75ceba5be9954018d..9d3d8f6185bb3e955b226ad29f2d70305b5d0561 100644 (file)
@@ -17,6 +17,8 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 
+#![deny(rust_2018_idioms)]
+
 #![feature(allocator_api)]
 #![feature(alloc)]
 #![feature(core_intrinsics)]
 #![panic_runtime]
 #![feature(panic_runtime)]
 
-extern crate alloc;
-extern crate libc;
-#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
-extern crate unwind;
-
 use alloc::boxed::Box;
 use core::intrinsics;
 use core::mem;
@@ -87,7 +84,7 @@
                                                   vtable_ptr: *mut usize)
                                                   -> u32 {
     let mut payload = imp::payload();
-    if intrinsics::try(f, data, &mut payload as *mut _ as *mut _) == 0 {
+    if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 {
         0
     } else {
         let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
index f52d010815c5df691af3b3620a6cebe024d3d8db..996fdb931eff2d49000f7d56212adea96c5d0172 100644 (file)
@@ -52,7 +52,7 @@
 use core::mem;
 use core::raw;
 
-use windows as c;
+use crate::windows as c;
 use libc::{c_int, c_uint};
 
 // First up, a whole bunch of type definitions. There's a few platform-specific
@@ -301,5 +301,5 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
 #[lang = "eh_personality"]
 #[cfg(not(test))]
 fn rust_eh_personality() {
-    unsafe { ::core::intrinsics::abort() }
+    unsafe { core::intrinsics::abort() }
 }
index 56ff6082190bcc3c72cdbfa1b886c844258bfa70..457ffcd34f9c7ad423cbeeed910b342e85655534 100644 (file)
@@ -9,8 +9,8 @@
 use core::any::Any;
 use core::intrinsics;
 use core::ptr;
-use dwarf::eh::{EHContext, EHAction, find_eh_action};
-use windows as c;
+use crate::dwarf::eh::{EHContext, EHAction, find_eh_action};
+use crate::windows as c;
 
 // Define our exception codes:
 // according to http://msdn.microsoft.com/en-us/library/het71c37(v=VS.80).aspx,
index 238f8f635415b5a1a9cbcb411b29392411087b11..6c061189d00d7915002da588f0452ce5645a6227 100644 (file)
@@ -5,7 +5,9 @@
 //! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and
 //! custom derive attributes`#[proc_macro_derive]`.
 //!
-//! See [the book](../book/first-edition/procedural-macros.html) for more.
+//! See [the book] for more.
+//!
+//! [the book]: ../book/ch19-06-macros.html#procedural-macros-for-generating-code-from-attributes
 
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
 #![deny(missing_docs)]
index 6644175bbd8a8e97928bd4c850e7730e9fe3024a..f46ff6f6062c2648037fbc0ecfe2ac3a665c6ea8 100644 (file)
@@ -1,3 +1,4 @@
+// ignore-tidy-linelength
 #![allow(non_snake_case)]
 
 // Error messages for EXXXX errors.
@@ -410,7 +411,7 @@ fn baz<'a>(x: &'a str, y: &str) -> &str { }
 Lifetime elision in implementation headers was part of the lifetime elision
 RFC. It is, however, [currently unimplemented][iss15872].
 
-[book-le]: https://doc.rust-lang.org/nightly/book/first-edition/lifetimes.html#lifetime-elision
+[book-le]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision
 [iss15872]: https://github.com/rust-lang/rust/issues/15872
 "##,
 
@@ -646,7 +647,9 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
 #![no_std]
 ```
 
-See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
+See also the [unstable book][1].
+
+[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
 "##,
 
 E0214: r##"
@@ -1713,7 +1716,7 @@ fn main() {
 ```
 
 To understand better how closures work in Rust, read:
-https://doc.rust-lang.org/book/first-edition/closures.html
+https://doc.rust-lang.org/book/ch13-01-closures.html
 "##,
 
 E0580: r##"
index cc5b105bad0d42a80e03f3b54ee714e6ffccdb53..84487c40f874508f4d6ad469d941139d1109266f 100644 (file)
@@ -3859,7 +3859,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 hir::ExprKind::Call(f, args.iter().map(|x| self.lower_expr(x)).collect())
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let hir_seg = self.lower_path_segment(
+                let hir_seg = P(self.lower_path_segment(
                     e.span,
                     seg,
                     ParamMode::Optional,
@@ -3867,7 +3867,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     ParenthesizedGenericArgs::Err,
                     ImplTraitContext::disallowed(),
                     None,
-                );
+                ));
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
                 hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
             }
@@ -4148,7 +4148,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     node: if is_unit {
                         hir::ExprKind::Path(struct_path)
                     } else {
-                        hir::ExprKind::Struct(struct_path, fields, None)
+                        hir::ExprKind::Struct(P(struct_path), fields, None)
                     },
                     span: e.span,
                     attrs: e.attrs.clone(),
@@ -4220,13 +4220,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 hir::ExprKind::InlineAsm(P(hir_asm), outputs, inputs)
             }
             ExprKind::Struct(ref path, ref fields, ref maybe_expr) => hir::ExprKind::Struct(
-                self.lower_qpath(
+                P(self.lower_qpath(
                     e.id,
                     &None,
                     path,
                     ParamMode::Optional,
                     ImplTraitContext::disallowed(),
-                ),
+                )),
                 fields.iter().map(|x| self.lower_field(x)).collect(),
                 maybe_expr.as_ref().map(|x| P(self.lower_expr(x))),
             ),
index 692b7fd37d28d2868fa94f21fd5e81c9d3379855..b6cf4c1b84d0c6454b91bfb8374518c31eef8756 100644 (file)
@@ -127,9 +127,9 @@ fn associated_body(self) -> Option<BodyId> {
         }
     }
 
-    fn is_body_owner(self, node_id: NodeId) -> bool {
+    fn is_body_owner(self, hir_id: HirId) -> bool {
         match self.associated_body() {
-            Some(b) => b.node_id == node_id,
+            Some(b) => b.hir_id == hir_id,
             None => false,
         }
     }
@@ -438,7 +438,7 @@ pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem {
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body {
-        self.read(id.node_id);
+        self.read_by_hir_id(id.hir_id);
 
         // N.B., intentionally bypass `self.forest.krate()` so that we
         // do not trigger a read of the whole krate here
@@ -462,9 +462,10 @@ pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<FnDecl> {
     /// Returns the `NodeId` that corresponds to the definition of
     /// which this is the body of, i.e., a `fn`, `const` or `static`
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
-    pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
+    pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> NodeId {
+        let node_id = self.hir_to_node_id(hir_id);
         let parent = self.get_parent_node(node_id);
-        assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(node_id)));
+        assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(hir_id)));
         parent
     }
 
@@ -488,6 +489,12 @@ pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
         }
     }
 
+    // FIXME(@ljedrz): replace the NodeId variant
+    pub fn maybe_body_owned_by_by_hir_id(&self, id: HirId) -> Option<BodyId> {
+        let node_id = self.hir_to_node_id(id);
+        self.maybe_body_owned_by(node_id)
+    }
+
     /// Given a body owner's id, returns the `BodyId` associated with it.
     pub fn body_owned_by(&self, id: NodeId) -> BodyId {
         self.maybe_body_owned_by(id).unwrap_or_else(|| {
@@ -521,6 +528,12 @@ pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
         }
     }
 
+    // FIXME(@ljedrz): replace the NodeId variant
+    pub fn body_owner_kind_by_hir_id(&self, id: HirId) -> BodyOwnerKind {
+        let node_id = self.hir_to_node_id(id);
+        self.body_owner_kind(node_id)
+    }
+
     pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(id) {
             Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id,
@@ -837,6 +850,12 @@ pub fn get_module_parent(&self, id: NodeId) -> DefId {
         self.local_def_id(self.get_module_parent_node(id))
     }
 
+    // FIXME(@ljedrz): replace the NodeId variant
+    pub fn get_module_parent_by_hir_id(&self, id: HirId) -> DefId {
+        let node_id = self.hir_to_node_id(id);
+        self.get_module_parent(node_id)
+    }
+
     /// Returns the `NodeId` of `id`'s nearest module parent, or `id` itself if no
     /// module parent is in this map.
     pub fn get_module_parent_node(&self, id: NodeId) -> NodeId {
index bf16ec0be83e797b3dbefac96690ff3d10e60404..d774359fa79ec2fb8f9b242cab2416ddd6d79943 100644 (file)
@@ -72,7 +72,7 @@ macro_rules! hir_vec {
 /// the `local_id` part of the `HirId` changing, which is a very useful property in
 /// incremental compilation where we have to persist things through changes to
 /// the code base.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
 pub struct HirId {
     pub owner: DefIndex,
     pub local_id: ItemLocalId,
@@ -1234,7 +1234,7 @@ pub enum UnsafeSource {
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct BodyId {
-    pub node_id: NodeId,
+    pub hir_id: HirId,
 }
 
 /// The body of a function, closure, or constant value. In the case of
@@ -1268,7 +1268,7 @@ pub struct Body {
 impl Body {
     pub fn id(&self) -> BodyId {
         BodyId {
-            node_id: self.value.id
+            hir_id: self.value.hir_id,
         }
     }
 }
@@ -1319,6 +1319,10 @@ pub struct Expr {
     pub hir_id: HirId,
 }
 
+// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 72);
+
 impl Expr {
     pub fn precedence(&self) -> ExprPrecedence {
         match self.node {
@@ -1438,7 +1442,7 @@ pub enum ExprKind {
     /// and the remaining elements are the rest of the arguments.
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
     /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
-    MethodCall(PathSegment, Span, HirVec<Expr>),
+    MethodCall(P<PathSegment>, Span, HirVec<Expr>),
     /// A tuple (e.g., `(a, b, c ,d)`).
     Tup(HirVec<Expr>),
     /// A binary operation (e.g., `a + b`, `a * b`).
@@ -1506,7 +1510,7 @@ pub enum ExprKind {
     ///
     /// For example, `Foo {x: 1, y: 2}`, or
     /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
-    Struct(QPath, HirVec<Field>, Option<P<Expr>>),
+    Struct(P<QPath>, HirVec<Field>, Option<P<Expr>>),
 
     /// An array literal constructed from one repeated element.
     ///
@@ -2290,7 +2294,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Impl(..) => "item",
+            ItemKind::Impl(..) => "impl",
         }
     }
 
index 712fd360fbb6fffd31e423b2ad96f18387a6de9a..b10e89373259798624d97801c4f5939b5967094b 100644 (file)
@@ -989,8 +989,8 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for hir::BodyId {
     fn to_stable_hash_key(&self,
                           hcx: &StableHashingContext<'a>)
                           -> (DefPathHash, hir::ItemLocalId) {
-        let hir::BodyId { node_id } = *self;
-        node_id.to_stable_hash_key(hcx)
+        let hir::BodyId { hir_id } = *self;
+        hir_id.to_stable_hash_key(hcx)
     }
 }
 
index ff4e520d8e08e78d0b09da1ebde32a5a98d27bc7..705d9c4cf93ea94acc0388fcaae8ffe867476452 100644 (file)
@@ -508,22 +508,31 @@ fn note_error_origin(
                     }
                 }
             }
-            ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
+            ObligationCauseCode::MatchExpressionArm {
+                source,
+                ref prior_arms,
+                last_ty,
+                ..
+            } => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
-                    let msg = "`if let` arm with an incompatible type";
-                    if self.tcx.sess.source_map().is_multiline(arm_span) {
-                        err.span_note(arm_span, msg);
-                    } else {
-                        err.span_label(arm_span, msg);
-                    }
+                    let msg = "`if let` arms have incompatible types";
+                    err.span_label(cause.span, msg);
                 }
                 hir::MatchSource::TryDesugar => {}
                 _ => {
-                    let msg = "match arm with an incompatible type";
-                    if self.tcx.sess.source_map().is_multiline(arm_span) {
-                        err.span_note(arm_span, msg);
-                    } else {
-                        err.span_label(arm_span, msg);
+                    let msg = "`match` arms have incompatible types";
+                    err.span_label(cause.span, msg);
+                    if prior_arms.len() <= 4 {
+                        for sp in prior_arms {
+                            err.span_label(*sp, format!(
+                                "this is found to be of type `{}`",
+                                last_ty,
+                            ));
+                        }
+                    } else if let Some(sp) = prior_arms.last() {
+                        err.span_label(*sp, format!(
+                            "this and all prior arms are found to be of type `{}`", last_ty,
+                        ));
                     }
                 }
             },
index 0fbdbe15a3c547fbbefce0b7cc1f543471904f08..9e0e48e474118fd14730ee363d1f804427b4b026 100644 (file)
@@ -105,7 +105,7 @@ pub fn need_type_info_err(&self,
         };
 
         if let Some(body_id) = body_id {
-            let expr = self.tcx.hir().expect_expr(body_id.node_id);
+            let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id);
             local_visitor.visit_expr(expr);
         }
 
index 88423086058256bc51738efa135d0793e943c230..a61771b2a4eeab2884b672a2c33391e0ec67b96d 100644 (file)
@@ -7,6 +7,7 @@
 pub use self::ValuePairs::*;
 pub use crate::ty::IntVarValue;
 
+use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::infer::canonical::{Canonical, CanonicalVarValues};
 use crate::middle::free_region::RegionRelations;
@@ -203,7 +204,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     // for each body-id in this map, which will process the
     // obligations within. This is expected to be done 'late enough'
     // that all type inference variables have been bound and so forth.
-    pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
+    pub region_obligations: RefCell<Vec<(hir::HirId, RegionObligation<'tcx>)>>,
 
     /// What is the innermost universe we have created? Starts out as
     /// `UniverseIndex::root()` but grows from there as we enter
@@ -1433,7 +1434,7 @@ pub fn closure_sig(
     pub fn partially_normalize_associated_types_in<T>(
         &self,
         span: Span,
-        body_id: ast::NodeId,
+        body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
     ) -> InferOk<'tcx, T>
index 0e2c49a00dafe90a2dc2887586940d93deebee27..1f81321d22d6ed1099dd7082ef905130050c1b3c 100644 (file)
@@ -98,7 +98,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
         parent_def_id: DefId,
-        body_id: ast::NodeId,
+        body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
     ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
@@ -632,7 +632,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     parent_def_id: DefId,
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
     opaque_types: OpaqueTypeMap<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
index 43afb60ee17317321148c749e43efd14dc5cf1c7..39aa51a95f793cb9bebe71b05f16bafc9f493df5 100644 (file)
@@ -1,7 +1,7 @@
 use crate::infer::outlives::free_region_map::FreeRegionMap;
 use crate::infer::{GenericKind, InferCtxt};
+use crate::hir;
 use rustc_data_structures::fx::FxHashMap;
-use syntax::ast;
 use syntax_pos::Span;
 use crate::traits::query::outlives_bounds::{self, OutlivesBound};
 use crate::ty::{self, Ty};
@@ -55,7 +55,7 @@ pub struct OutlivesEnvironment<'tcx> {
     // results when proving outlives obligations like `T: 'x` later
     // (e.g., if `T: 'x` must be proven within the body B1, then we
     // know it is true if either `'a: 'x` or `'b: 'x`).
-    region_bound_pairs_map: FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
+    region_bound_pairs_map: FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
 
     // Used to compute `region_bound_pairs_map`: contains the set of
     // in-scope region-bound pairs thus far.
@@ -87,7 +87,7 @@ pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
     }
 
     /// Borrows current value of the `region_bound_pairs`.
-    pub fn region_bound_pairs_map(&self) -> &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>> {
+    pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>> {
         &self.region_bound_pairs_map
     }
 
@@ -162,7 +162,7 @@ pub fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'gcx, 'tcx>,
         fn_sig_tys: &[Ty<'tcx>],
-        body_id: ast::NodeId,
+        body_id: hir::HirId,
         span: Span,
     ) {
         debug!("add_implied_bounds()");
@@ -176,7 +176,7 @@ pub fn add_implied_bounds(
     }
 
     /// Save the current set of region-bound pairs under the given `body_id`.
-    pub fn save_implied_bounds(&mut self, body_id: ast::NodeId) {
+    pub fn save_implied_bounds(&mut self, body_id: hir::HirId) {
         let old = self.region_bound_pairs_map.insert(
             body_id,
             self.region_bound_pairs_accum.clone(),
index c40fbfb25e42246972347f4fb0cc8c7e9c1c7f34..bbda3d2fdbf84d9ac15ebb7d186ac0e7cd65fd52 100644 (file)
@@ -63,7 +63,7 @@
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
 use rustc_data_structures::fx::FxHashMap;
-use syntax::ast;
+use crate::hir;
 use crate::traits::ObligationCause;
 use crate::ty::outlives::Component;
 use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
@@ -76,7 +76,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// information).
     pub fn register_region_obligation(
         &self,
-        body_id: ast::NodeId,
+        body_id: hir::HirId,
         obligation: RegionObligation<'tcx>,
     ) {
         debug!(
@@ -110,7 +110,7 @@ pub fn register_region_obligation_with_cause(
     }
 
     /// Trait queries just want to pass back type obligations "as is"
-    pub fn take_registered_region_obligations(&self) -> Vec<(ast::NodeId, RegionObligation<'tcx>)> {
+    pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
         ::std::mem::replace(&mut *self.region_obligations.borrow_mut(), vec![])
     }
 
@@ -149,7 +149,7 @@ pub fn take_registered_region_obligations(&self) -> Vec<(ast::NodeId, RegionObli
     /// processed.
     pub fn process_registered_region_obligations(
         &self,
-        region_bound_pairs_map: &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
+        region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
         implicit_region_bound: Option<ty::Region<'tcx>>,
         param_env: ty::ParamEnv<'tcx>,
     ) {
index 6f10b0e2c0e67a0a96dffa8e986d784a221157d4..655707ff9bd0da0f962192f28c0bd5d0eb690818 100644 (file)
@@ -557,7 +557,7 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
             }
             BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
                 if !replaces.is_empty() {
-                    db.multipart_suggestion(
+                    db.tool_only_multipart_suggestion(
                         &message,
                         replaces,
                         Applicability::MachineApplicable,
index 68ce4024ae4e6f7ad51dfd01db97b209dd2f318a..30a43c7a92595c57c2b5a2ac25e14949a7d37ef5 100644 (file)
@@ -322,14 +322,17 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> {
-    fn check_missing_stability(&self, id: NodeId, span: Span) {
+    fn check_missing_stability(&self, id: NodeId, span: Span, name: &str) {
         let hir_id = self.tcx.hir().node_to_hir_id(id);
         let stab = self.tcx.stability().local_stability(hir_id);
         let is_error = !self.tcx.sess.opts.test &&
                         stab.is_none() &&
                         self.access_levels.is_reachable(id);
         if is_error {
-            self.tcx.sess.span_err(span, "This node does not have a stability attribute");
+            self.tcx.sess.span_err(
+                span,
+                &format!("{} has missing stability attribute", name),
+            );
         }
     }
 }
@@ -347,42 +350,42 @@ fn visit_item(&mut self, i: &'tcx Item) {
             // optional. They inherit stability from their parents when unannotated.
             hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {}
 
-            _ => self.check_missing_stability(i.id, i.span)
+            _ => self.check_missing_stability(i.id, i.span, i.node.descriptive_variant())
         }
 
         intravisit::walk_item(self, i)
     }
 
     fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        self.check_missing_stability(ti.id, ti.span);
+        self.check_missing_stability(ti.id, ti.span, "item");
         intravisit::walk_trait_item(self, ti);
     }
 
     fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
         let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id));
         if self.tcx.impl_trait_ref(impl_def_id).is_none() {
-            self.check_missing_stability(ii.id, ii.span);
+            self.check_missing_stability(ii.id, ii.span, "item");
         }
         intravisit::walk_impl_item(self, ii);
     }
 
     fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: NodeId) {
-        self.check_missing_stability(var.node.data.id(), var.span);
+        self.check_missing_stability(var.node.data.id(), var.span, "variant");
         intravisit::walk_variant(self, var, g, item_id);
     }
 
     fn visit_struct_field(&mut self, s: &'tcx StructField) {
-        self.check_missing_stability(s.id, s.span);
+        self.check_missing_stability(s.id, s.span, "field");
         intravisit::walk_struct_field(self, s);
     }
 
     fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) {
-        self.check_missing_stability(i.id, i.span);
+        self.check_missing_stability(i.id, i.span, i.node.descriptive_variant());
         intravisit::walk_foreign_item(self, i);
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
-        self.check_missing_stability(md.id, md.span);
+        self.check_missing_stability(md.id, md.span, "macro");
     }
 }
 
@@ -593,37 +596,11 @@ pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> Ev
         // Deprecated attributes apply in-crate and cross-crate.
         if let Some(id) = id {
             if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) {
-                // If the deprecation is scheduled for a future Rust
-                // version, then we should display no warning message.
-                let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since {
-                    let since = sym.as_str();
-                    if !deprecation_in_effect(&since) {
-                        Some(since)
-                    } else {
-                        None
-                    }
-                } else {
-                    None
-                };
-
                 let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id));
                 let skip = self.lookup_deprecation_entry(parent_def_id)
                                .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
 
-                if let Some(since) = deprecated_in_future_version {
-                    let path = self.item_path_str(def_id);
-                    let message = format!("use of item '{}' \
-                                           that will be deprecated in future version {}",
-                                          path,
-                                          since);
-
-                    lint_deprecated(def_id,
-                                    id,
-                                    depr_entry.attr.note,
-                                    None,
-                                    &message,
-                                    lint::builtin::DEPRECATED_IN_FUTURE);
-                } else if !skip {
+                if !skip {
                     let path = self.item_path_str(def_id);
                     let message = format!("use of deprecated item '{}'", path);
                     lint_deprecated(def_id,
@@ -866,7 +843,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
             tcx,
             access_levels,
         };
-        missing.check_missing_stability(ast::CRATE_NODE_ID, krate.span);
+        missing.check_missing_stability(ast::CRATE_NODE_ID, krate.span, "crate");
         intravisit::walk_crate(&mut missing, krate);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
index 012b9e5034caee0586c0ddb4ed9529b89e7ff2e8..8957bbaa4ad7d9eb3df9793e8398b28e2e6e56fd 100644 (file)
@@ -202,7 +202,7 @@ pub fn find_auto_trait_generics<A>(
                 full_env,
                 ty,
                 trait_did,
-                ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID),
+                ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID),
             );
             fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
                 panic!(
@@ -315,7 +315,7 @@ pub fn evaluate_predicates<'b, 'gcx, 'c>(
             user_env.caller_bounds.iter().cloned().collect();
 
         let mut new_env = param_env.clone();
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
+        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
 
         while let Some(pred) = predicates.pop_front() {
             infcx.clear_caches();
@@ -669,7 +669,7 @@ pub fn evaluate_nested_obligations<
         select: &mut SelectionContext<'c, 'd, 'cx>,
         only_projections: bool,
     ) -> bool {
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
+        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
 
         for (obligation, mut predicate) in nested
             .map(|o| (o.clone(), o.predicate.clone()))
index a32838f0e4c0c356ce9c459817d2c4b13e771890..99d1e32d52398cdb15b7b048601c4f9e665cb820 100644 (file)
@@ -132,7 +132,7 @@ pub struct ObligationCause<'tcx> {
     /// (in particular, closures can add new assumptions). See the
     /// field `region_obligations` of the `FulfillmentContext` for more
     /// information.
-    pub body_id: ast::NodeId,
+    pub body_id: hir::HirId,
 
     pub code: ObligationCauseCode<'tcx>
 }
@@ -145,6 +145,7 @@ pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
             ObligationCauseCode::StartFunctionType => {
                 tcx.sess.source_map().def_span(self.span)
             }
+            ObligationCauseCode::MatchExpressionArm { arm_span, .. } => arm_span,
             _ => self.span,
         }
     }
@@ -223,6 +224,8 @@ pub enum ObligationCauseCode<'tcx> {
     MatchExpressionArm {
         arm_span: Span,
         source: hir::MatchSource,
+        prior_arms: Vec<Span>,
+        last_ty: Ty<'tcx>,
     },
 
     /// Computing common supertype in the pattern guard for the arms of a match expression
@@ -654,7 +657,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>(
     };
     let obligation = Obligation {
         param_env,
-        cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID),
+        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
         recursion_depth: 0,
         predicate: trait_ref.to_predicate(),
     };
@@ -677,7 +680,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>(
         // We can use a dummy node-id here because we won't pay any mind
         // to region obligations that arise (there shouldn't really be any
         // anyhow).
-        let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
+        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
 
         fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
 
@@ -1057,7 +1060,7 @@ fn with_depth(cause: ObligationCause<'tcx>,
     }
 
     pub fn misc(span: Span,
-                body_id: ast::NodeId,
+                body_id: hir::HirId,
                 param_env: ty::ParamEnv<'tcx>,
                 trait_ref: O)
                 -> Obligation<'tcx, O> {
@@ -1075,18 +1078,18 @@ pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> {
 impl<'tcx> ObligationCause<'tcx> {
     #[inline]
     pub fn new(span: Span,
-               body_id: ast::NodeId,
+               body_id: hir::HirId,
                code: ObligationCauseCode<'tcx>)
                -> ObligationCause<'tcx> {
-        ObligationCause { span: span, body_id: body_id, code: code }
+        ObligationCause { span, body_id, code }
     }
 
-    pub fn misc(span: Span, body_id: ast::NodeId) -> ObligationCause<'tcx> {
-        ObligationCause { span: span, body_id: body_id, code: MiscObligation }
+    pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
+        ObligationCause { span, body_id, code: MiscObligation }
     }
 
     pub fn dummy() -> ObligationCause<'tcx> {
-        ObligationCause { span: DUMMY_SP, body_id: ast::CRATE_NODE_ID, code: MiscObligation }
+        ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }
     }
 }
 
index 6fe361d5adf6d66a57f4d836702564c96bc54490..954de15905fb7092875e64a2178671e232f5e8bc 100644 (file)
@@ -1,6 +1,6 @@
 use crate::infer::InferCtxt;
 use crate::infer::canonical::OriginalQueryValues;
-use syntax::ast;
+use crate::hir;
 use syntax::source_map::Span;
 use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
 use crate::traits::query::NoSolution;
@@ -89,7 +89,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     pub fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        body_id: ast::NodeId,
+        body_id: hir::HirId,
         ty: Ty<'tcx>,
         span: Span,
     ) -> Vec<OutlivesBound<'tcx>> {
index c5cc9e8b401822907b339e0bdd5fdc7d864705bb..b5be1777fa0d8804c7dbba9afa31aee9a86c157d 100644 (file)
@@ -513,10 +513,21 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 trait_item_def_id,
             }),
             super::ExprAssignable => Some(super::ExprAssignable),
-            super::MatchExpressionArm { arm_span, source } => Some(super::MatchExpressionArm {
+            super::MatchExpressionArm {
                 arm_span,
-                source: source,
-            }),
+                source,
+                ref prior_arms,
+                last_ty,
+            } => {
+                tcx.lift(&last_ty).map(|last_ty| {
+                    super::MatchExpressionArm {
+                        arm_span,
+                        source,
+                        prior_arms: prior_arms.clone(),
+                        last_ty,
+                    }
+                })
+            }
             super::MatchExpressionArmPattern { span, ty } => {
                 tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
             }
index 70f72acad1fb68be2cc00cf62da3aec4bb53ff3c..1bb67b3ffaae84cc6e09431d62c19971f5637757 100644 (file)
@@ -39,7 +39,7 @@
 use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
 use std::slice;
 use std::{mem, ptr};
-use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
+use syntax::ast::{self, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
 use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
@@ -2795,7 +2795,7 @@ pub fn field_index(self, node_id: NodeId, tables: &TypeckTables<'_>) -> usize {
 
     pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
         variant.fields.iter().position(|field| {
-            self.adjust_ident(ident, variant.did, DUMMY_NODE_ID).0 == field.ident.modern()
+            self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern()
         })
     }
 
@@ -3003,10 +3003,10 @@ pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
     /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed
     /// definition's parent/scope to perform comparison.
     pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool {
-        self.adjust_ident(use_name, def_parent_def_id, DUMMY_NODE_ID).0 == def_name.modern()
+        self.adjust_ident(use_name, def_parent_def_id, hir::DUMMY_HIR_ID).0 == def_name.modern()
     }
 
-    pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
+    pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: hir::HirId) -> (Ident, DefId) {
         ident = ident.modern();
         let target_expansion = match scope.krate {
             LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index),
@@ -3015,8 +3015,8 @@ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ide
         let scope = match ident.span.adjust(target_expansion) {
             Some(actual_expansion) =>
                 self.hir().definitions().parent_module_of_macro_def(actual_expansion),
-            None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
-            None => self.hir().get_module_parent(block),
+            None if block == hir::DUMMY_HIR_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
+            None => self.hir().get_module_parent_by_hir_id(block),
         };
         (ident, scope)
     }
@@ -3193,8 +3193,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None }
     );
 
-    let body_id = tcx.hir().as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
-        tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+    let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| {
+        tcx.hir().maybe_body_owned_by_by_hir_id(id).map_or(id, |body| body.hir_id)
     });
     let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
     traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
index 267ee89a2ffed95f50e57487ab8b6909705899dd..233aff9de243fda3e600d2f30dd52d8a7d1049a4 100644 (file)
@@ -188,40 +188,6 @@ pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
 
         job.signal_complete();
     }
-
-    /// Executes a job by changing the ImplicitCtxt to point to the
-    /// new query job while it executes. It returns the diagnostics
-    /// captured during execution and the actual result.
-    #[inline(always)]
-    pub(super) fn start<'lcx, F, R>(
-        &self,
-        tcx: TyCtxt<'_, 'tcx, 'lcx>,
-        diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
-        compute: F)
-    -> R
-    where
-        F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R
-    {
-        // The TyCtxt stored in TLS has the same global interner lifetime
-        // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
-        // when accessing the ImplicitCtxt
-        tls::with_related_context(tcx, move |current_icx| {
-            // Update the ImplicitCtxt to point to our new query job
-            let new_icx = tls::ImplicitCtxt {
-                tcx: tcx.global_tcx(),
-                query: Some(self.job.clone()),
-                diagnostics,
-                layout_depth: current_icx.layout_depth,
-                task_deps: current_icx.task_deps,
-            };
-
-            // Use the ImplicitCtxt while we execute the query
-            tls::enter_context(&new_icx, |_| {
-                compute(tcx)
-            })
-        })
-    }
-
 }
 
 #[inline(always)]
@@ -265,6 +231,39 @@ pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+    /// Executes a job by changing the ImplicitCtxt to point to the
+    /// new query job while it executes. It returns the diagnostics
+    /// captured during execution and the actual result.
+    #[inline(always)]
+    pub(super) fn start_query<F, R>(
+        self,
+        job: Lrc<QueryJob<'gcx>>,
+        diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
+        compute: F)
+    -> R
+    where
+        F: for<'b, 'lcx> FnOnce(TyCtxt<'b, 'gcx, 'lcx>) -> R
+    {
+        // The TyCtxt stored in TLS has the same global interner lifetime
+        // as `self`, so we use `with_related_context` to relate the 'gcx lifetimes
+        // when accessing the ImplicitCtxt
+        tls::with_related_context(self, move |current_icx| {
+            // Update the ImplicitCtxt to point to our new query job
+            let new_icx = tls::ImplicitCtxt {
+                tcx: self.global_tcx(),
+                query: Some(job),
+                diagnostics,
+                layout_depth: current_icx.layout_depth,
+                task_deps: current_icx.task_deps,
+            };
+
+            // Use the ImplicitCtxt while we execute the query
+            tls::enter_context(&new_icx, |_| {
+                compute(self.global_tcx())
+            })
+        })
+    }
+
     #[inline(never)]
     #[cold]
     pub(super) fn report_cycle(
@@ -378,7 +377,7 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
             self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
 
             let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-                job.start(self, diagnostics, |tcx| {
+                self.start_query(job.job.clone(), diagnostics, |tcx| {
                     tcx.dep_graph.with_anon_task(dep_node.kind, || {
                         Q::compute(tcx.global_tcx(), key)
                     })
@@ -401,16 +400,23 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
         }
 
         if !dep_node.kind.is_input() {
-            if let Some((prev_dep_node_index,
-                         dep_node_index)) = self.dep_graph.try_mark_green_and_read(self,
-                                                                                   &dep_node) {
-                return Ok(self.load_from_disk_and_cache_in_memory::<Q>(
-                    key,
-                    job,
-                    prev_dep_node_index,
-                    dep_node_index,
-                    &dep_node
-                ))
+            // The diagnostics for this query will be
+            // promoted to the current session during
+            // try_mark_green(), so we can ignore them here.
+            let loaded = self.start_query(job.job.clone(), None, |tcx| {
+                let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node);
+                marked.map(|(prev_dep_node_index, dep_node_index)| {
+                    (tcx.load_from_disk_and_cache_in_memory::<Q>(
+                        key.clone(),
+                        prev_dep_node_index,
+                        dep_node_index,
+                        &dep_node
+                    ), dep_node_index)
+                })
+            });
+            if let Some((result, dep_node_index)) = loaded {
+                job.complete(&result, dep_node_index);
+                return Ok(result);
             }
         }
 
@@ -422,7 +428,6 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
     fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
         self,
         key: Q::Key,
-        job: JobOwner<'a, 'gcx, Q>,
         prev_dep_node_index: SerializedDepNodeIndex,
         dep_node_index: DepNodeIndex,
         dep_node: &DepNode
@@ -461,15 +466,10 @@ fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
 
             self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
 
-            // The diagnostics for this query have already been
-            // promoted to the current session during
-            // try_mark_green(), so we can ignore them here.
-            let result = job.start(self, None, |tcx| {
-                // The dep-graph for this computation is already in
-                // place
-                tcx.dep_graph.with_ignore(|| {
-                    Q::compute(tcx, key)
-                })
+            // The dep-graph for this computation is already in
+            // place
+            let result = self.dep_graph.with_ignore(|| {
+                Q::compute(self, key)
             });
 
             self.sess.profiler(|p| p.end_query(Q::NAME, Q::CATEGORY));
@@ -486,8 +486,6 @@ fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
             self.dep_graph.mark_loaded_from_cache(dep_node_index, true);
         }
 
-        job.complete(&result, dep_node_index);
-
         result
     }
 
@@ -540,7 +538,7 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
         self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY));
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-            job.start(self, diagnostics, |tcx| {
+            self.start_query(job.job.clone(), diagnostics, |tcx| {
                 if dep_node.kind.is_eval_always() {
                     tcx.dep_graph.with_eval_always_task(dep_node,
                                                         tcx,
index ffb5471e34fbf7e351e831700da368bc1821834f..282bf1219fa5c174deca13a16c972947c71129e5 100644 (file)
@@ -1,10 +1,10 @@
+use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::infer::InferCtxt;
 use crate::ty::subst::Substs;
 use crate::traits;
 use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use std::iter::once;
-use syntax::ast;
 use syntax_pos::Span;
 use crate::middle::lang_items;
 
@@ -16,7 +16,7 @@
 /// say "$0 is WF if $0 is WF".
 pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                    param_env: ty::ParamEnv<'tcx>,
-                                   body_id: ast::NodeId,
+                                   body_id: hir::HirId,
                                    ty: Ty<'tcx>,
                                    span: Span)
                                    -> Option<Vec<traits::PredicateObligation<'tcx>>>
@@ -42,7 +42,7 @@ pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 /// if `Bar: Eq`.
 pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                          param_env: ty::ParamEnv<'tcx>,
-                                         body_id: ast::NodeId,
+                                         body_id: hir::HirId,
                                          trait_ref: &ty::TraitRef<'tcx>,
                                          span: Span)
                                          -> Vec<traits::PredicateObligation<'tcx>>
@@ -54,7 +54,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 
 pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                              param_env: ty::ParamEnv<'tcx>,
-                                             body_id: ast::NodeId,
+                                             body_id: hir::HirId,
                                              predicate: &ty::Predicate<'tcx>,
                                              span: Span)
                                              -> Vec<traits::PredicateObligation<'tcx>>
@@ -103,7 +103,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
     span: Span,
     out: Vec<traits::PredicateObligation<'tcx>>,
 }
index 85c4ca7bd379ee7e7ade5623719af201a5ad97bd..307df163866392dcdabd7314bc633cb99e31b421 100644 (file)
@@ -404,7 +404,7 @@ fn closure_to_block(closure_id: LocalDefId,
     match tcx.hir().get(closure_id) {
         Node::Expr(expr) => match expr.node {
             hir::ExprKind::Closure(.., body_id, _, _) => {
-                body_id.node_id
+                tcx.hir().hir_to_node_id(body_id.hir_id)
             }
             _ => {
                 bug!("encountered non-closure id: {}", closure_id)
index 09804a706ec98f19ef7c6157948fba66b21cee36..e5b290b55c22e5ad915562d44361a26c9eceb84b 100644 (file)
@@ -296,6 +296,11 @@ macro_rules! controller_entry_point {
                         (control.after_analysis.callback)(&mut state);
                     });
 
+                    // Plugins like clippy and rust-semverver stop the analysis early,
+                    // but want to still return an error if errors during the analysis
+                    // happened:
+                    tcx.sess.compile_status()?;
+
                     if control.after_analysis.stop == Compilation::Stop {
                         return result.and_then(|_| Err(CompileIncomplete::Stopped));
                     }
index 2c410f69bfc662cd8a0128e9c800b499aa1100fa..851b19e8177b53917f37cf4a9bcab637fb5f2abe 100644 (file)
@@ -1,4 +1,5 @@
 use crate::CodeSuggestion;
+use crate::SuggestionStyle;
 use crate::SubstitutionPart;
 use crate::Substitution;
 use crate::Applicability;
@@ -243,7 +244,33 @@ pub fn multipart_suggestion(
                     .collect(),
             }],
             msg: msg.to_owned(),
-            show_code_when_inline: true,
+            style: SuggestionStyle::ShowCode,
+            applicability,
+        });
+        self
+    }
+
+    /// Prints out a message with for a multipart suggestion without showing the suggested code.
+    ///
+    /// This is intended to be used for suggestions that are obvious in what the changes need to
+    /// be from the message, showing the span label inline would be visually unpleasant
+    /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
+    /// improve understandability.
+    pub fn tool_only_multipart_suggestion(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: vec![Substitution {
+                parts: suggestion
+                    .into_iter()
+                    .map(|(span, snippet)| SubstitutionPart { snippet, span })
+                    .collect(),
+            }],
+            msg: msg.to_owned(),
+            style: SuggestionStyle::CompletelyHidden,
             applicability,
         });
         self
@@ -277,7 +304,7 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str,
                 }],
             }],
             msg: msg.to_owned(),
-            show_code_when_inline: true,
+            style: SuggestionStyle::ShowCode,
             applicability,
         });
         self
@@ -295,7 +322,7 @@ pub fn span_suggestions(&mut self, sp: Span, msg: &str,
                 }],
             }).collect(),
             msg: msg.to_owned(),
-            show_code_when_inline: true,
+            style: SuggestionStyle::ShowCode,
             applicability,
         });
         self
@@ -316,7 +343,51 @@ pub fn span_suggestion_short(
                 }],
             }],
             msg: msg.to_owned(),
-            show_code_when_inline: false,
+            style: SuggestionStyle::HideCodeInline,
+            applicability,
+        });
+        self
+    }
+
+    /// Prints out a message with for a suggestion without showing the suggested code.
+    ///
+    /// This is intended to be used for suggestions that are obvious in what the changes need to
+    /// be from the message, showing the span label inline would be visually unpleasant
+    /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
+    /// improve understandability.
+    pub fn span_suggestion_hidden(
+        &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability
+    ) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: vec![Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet: suggestion,
+                    span: sp,
+                }],
+            }],
+            msg: msg.to_owned(),
+            style: SuggestionStyle::HideCodeInline,
+            applicability,
+        });
+        self
+    }
+
+    /// Adds a suggestion to the json output, but otherwise remains silent/undisplayed in the cli.
+    ///
+    /// This is intended to be used for suggestions that are *very* obvious in what the changes
+    /// need to be from the message, but we still want other tools to be able to apply them.
+    pub fn tool_only_span_suggestion(
+        &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability
+    ) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: vec![Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet: suggestion,
+                    span: sp,
+                }],
+            }],
+            msg: msg.to_owned(),
+            style: SuggestionStyle::CompletelyHidden,
             applicability: applicability,
         });
         self
index 9d5e8d10b1772ff8c56108d2ae7feed832fa683a..8a30790174d45bec2886204aaff5dc2a2c211e48 100644 (file)
@@ -205,6 +205,24 @@ pub fn multipart_suggestion(
         self
     }
 
+    pub fn tool_only_multipart_suggestion(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.tool_only_multipart_suggestion(
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
+
+
     pub fn span_suggestion(
         &mut self,
         sp: Span,
@@ -261,6 +279,45 @@ pub fn span_suggestion_short(
         );
         self
     }
+
+    pub fn span_suggestion_hidden(
+        &mut self,
+        sp: Span,
+        msg: &str,
+        suggestion: String,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.span_suggestion_hidden(
+            sp,
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
+
+    pub fn tool_only_span_suggestion(
+        &mut self,
+        sp: Span,
+        msg: &str,
+        suggestion: String,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.allow_suggestions {
+            return self
+        }
+        self.diagnostic.tool_only_span_suggestion(
+            sp,
+            msg,
+            suggestion,
+            applicability,
+        );
+        self
+    }
+
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
index 1c0c9d137e40fedfa4084f2696a9919d6730a180..e9f269b6e2410b311fbee1c6ad15fd632baf17fe 100644 (file)
@@ -2,7 +2,10 @@
 
 use syntax_pos::{SourceFile, Span, MultiSpan};
 
-use crate::{Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, SourceMapperDyn, DiagnosticId};
+use crate::{
+    Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic,
+    SuggestionStyle, SourceMapperDyn, DiagnosticId,
+};
 use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use crate::styled_buffer::StyledBuffer;
 
@@ -43,9 +46,14 @@ fn emit(&mut self, db: &DiagnosticBuilder<'_>) {
                // don't display long messages as labels
                sugg.msg.split_whitespace().count() < 10 &&
                // don't display multiline suggestions as labels
-               !sugg.substitutions[0].parts[0].snippet.contains('\n') {
+               !sugg.substitutions[0].parts[0].snippet.contains('\n') &&
+               // when this style is set we want the suggestion to be a message, not inline
+               sugg.style != SuggestionStyle::HideCodeAlways &&
+               // trivial suggestion for tooling's sake, never shown
+               sugg.style != SuggestionStyle::CompletelyHidden
+            {
                 let substitution = &sugg.substitutions[0].parts[0].snippet.trim();
-                let msg = if substitution.len() == 0 || !sugg.show_code_when_inline {
+                let msg = if substitution.len() == 0 || sugg.style.hide_inline() {
                     // This substitution is only removal or we explicitly don't want to show the
                     // code inline, don't show it
                     format!("help: {}", sugg.msg)
@@ -942,14 +950,15 @@ fn style_or_override(style: Style, override_style: Option<Style>) -> Style {
         }
     }
 
-    fn emit_message_default(&mut self,
-                            msp: &MultiSpan,
-                            msg: &[(String, Style)],
-                            code: &Option<DiagnosticId>,
-                            level: &Level,
-                            max_line_num_len: usize,
-                            is_secondary: bool)
-                            -> io::Result<()> {
+    fn emit_message_default(
+        &mut self,
+        msp: &MultiSpan,
+        msg: &[(String, Style)],
+        code: &Option<DiagnosticId>,
+        level: &Level,
+        max_line_num_len: usize,
+        is_secondary: bool,
+    ) -> io::Result<()> {
         let mut buffer = StyledBuffer::new();
         let header_style = if is_secondary {
             Style::HeaderMsg
@@ -1184,11 +1193,12 @@ fn emit_message_default(&mut self,
 
     }
 
-    fn emit_suggestion_default(&mut self,
-                               suggestion: &CodeSuggestion,
-                               level: &Level,
-                               max_line_num_len: usize)
-                               -> io::Result<()> {
+    fn emit_suggestion_default(
+        &mut self,
+        suggestion: &CodeSuggestion,
+        level: &Level,
+        max_line_num_len: usize,
+    ) -> io::Result<()> {
         if let Some(ref sm) = self.sm {
             let mut buffer = StyledBuffer::new();
 
@@ -1198,11 +1208,13 @@ fn emit_suggestion_default(&mut self,
                 buffer.append(0, &level_str, Style::Level(level.clone()));
                 buffer.append(0, ": ", Style::HeaderMsg);
             }
-            self.msg_to_buffer(&mut buffer,
-                               &[(suggestion.msg.to_owned(), Style::NoStyle)],
-                               max_line_num_len,
-                               "suggestion",
-                               Some(Style::HeaderMsg));
+            self.msg_to_buffer(
+                &mut buffer,
+                &[(suggestion.msg.to_owned(), Style::NoStyle)],
+                max_line_num_len,
+                "suggestion",
+                Some(Style::HeaderMsg),
+            );
 
             // Render the replacements for each suggestion
             let suggestions = suggestion.splice_lines(&**sm);
@@ -1340,22 +1352,42 @@ fn emit_messages_default(&mut self,
                 if !self.short_message {
                     for child in children {
                         let span = child.render_span.as_ref().unwrap_or(&child.span);
-                        match self.emit_message_default(&span,
-                                                        &child.styled_message(),
-                                                        &None,
-                                                        &child.level,
-                                                        max_line_num_len,
-                                                        true) {
+                        match self.emit_message_default(
+                            &span,
+                            &child.styled_message(),
+                            &None,
+                            &child.level,
+                            max_line_num_len,
+                            true,
+                        ) {
                             Err(e) => panic!("failed to emit error: {}", e),
                             _ => ()
                         }
                     }
                     for sugg in suggestions {
-                        match self.emit_suggestion_default(sugg,
-                                                           &Level::Help,
-                                                           max_line_num_len) {
-                            Err(e) => panic!("failed to emit error: {}", e),
-                            _ => ()
+                        if sugg.style == SuggestionStyle::CompletelyHidden {
+                            // do not display this suggestion, it is meant only for tools
+                        } else if sugg.style == SuggestionStyle::HideCodeAlways {
+                            match self.emit_message_default(
+                                &MultiSpan::new(),
+                                &[(sugg.msg.to_owned(), Style::HeaderMsg)],
+                                &None,
+                                &Level::Help,
+                                max_line_num_len,
+                                true,
+                            ) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        } else {
+                            match self.emit_suggestion_default(
+                                sugg,
+                                &Level::Help,
+                                max_line_num_len,
+                            ) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
                         }
                     }
                 }
index 93d33d9936187601db7e83ba94df4b05783a21fc..87b47515268359b1331af2c676fd278fb14b02a3 100644 (file)
@@ -69,6 +69,29 @@ pub enum Applicability {
     Unspecified,
 }
 
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, RustcEncodable, RustcDecodable)]
+pub enum SuggestionStyle {
+    /// Hide the suggested code when displaying this suggestion inline.
+    HideCodeInline,
+    /// Always hide the suggested code but display the message.
+    HideCodeAlways,
+    /// Do not display this suggestion in the cli output, it is only meant for tools.
+    CompletelyHidden,
+    /// Always show the suggested code.
+    /// This will *not* show the code if the suggestion is inline *and* the suggested code is
+    /// empty.
+    ShowCode,
+}
+
+impl SuggestionStyle {
+    fn hide_inline(&self) -> bool {
+        match *self {
+            SuggestionStyle::ShowCode => false,
+            _ => true,
+        }
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct CodeSuggestion {
     /// Each substitute can have multiple variants due to multiple
@@ -94,7 +117,8 @@ pub struct CodeSuggestion {
     /// ```
     pub substitutions: Vec<Substitution>,
     pub msg: String,
-    pub show_code_when_inline: bool,
+    /// Visual representation of this suggestion.
+    pub style: SuggestionStyle,
     /// Whether or not the suggestion is approximate
     ///
     /// Sometimes we may show suggestions with placeholders,
index c27d13be4935839357e58ec2020ad8e0049ea9c3..9ac582ebc42dab1b0cf0133606de3c81d4da7a59 100644 (file)
@@ -37,7 +37,7 @@
 ```
 
 See more:
-https://doc.rust-lang.org/book/first-edition/conditional-compilation.html
+https://doc.rust-lang.org/reference/attributes.html#conditional-compilation
 "##,
 
 E0458: r##"
index eb721754216382f97165079ec868127b714a66bd..31aa3c2782697184f614251c22b43003ecb54b33 100644 (file)
@@ -690,7 +690,7 @@ fn main() {
 }
 ```
 
-See also https://doc.rust-lang.org/book/first-edition/unsafe.html
+See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html
 "##,
 
 E0373: r##"
@@ -873,7 +873,7 @@ fn main() {
 If you wish to learn more about ownership in Rust, start with the chapter in the
 Book:
 
-https://doc.rust-lang.org/book/first-edition/ownership.html
+https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html
 "##,
 
 E0383: r##"
@@ -1207,7 +1207,7 @@ unsafe impl<T> Sync for NotThreadSafe<T> {}
 
 Please note that in rust, you can either have many immutable references, or one
 mutable reference. Take a look at
-https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
+https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html for more
 information. Example:
 
 
@@ -1374,7 +1374,7 @@ fn foo(a: &mut i32) {
 ```
 
 For more information on the rust ownership system, take a look at
-https://doc.rust-lang.org/stable/book/references-and-borrowing.html.
+https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html.
 "##,
 
 E0503: r##"
@@ -1430,7 +1430,7 @@ fn main() {
 ```
 
 You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/stable/book/references-and-borrowing.html
+http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
 "##,
 
 E0504: r##"
@@ -1614,7 +1614,7 @@ fn main() {
 ```
 
 You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/stable/book/references-and-borrowing.html
+http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
 "##,
 
 E0506: r##"
@@ -1825,7 +1825,7 @@ fn main() {
 ```
 
 You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
+http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
 "##,
 
 E0508: r##"
index a1a9e9baf1b2c0c19e0556327597568786ddff3e..c593be4e67f4577d0ce57c6ec09a8d624d3f61f4 100644 (file)
@@ -1174,9 +1174,9 @@ fn run_pass<'a, 'tcx>(&self,
         }
 
         let def_id = src.def_id();
-        let id = tcx.hir().as_local_node_id(def_id).unwrap();
+        let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         let mut const_promoted_temps = None;
-        let mode = match tcx.hir().body_owner_kind(id) {
+        let mode = match tcx.hir().body_owner_kind_by_hir_id(id) {
             hir::BodyOwnerKind::Closure => Mode::Fn,
             hir::BodyOwnerKind::Fn => {
                 if tcx.is_const_fn(def_id) {
index 1357f8fe79a0dae138dc3776f6b20e5b35fad936..8177de50776d64758e164dbf622de5d9f85fe882 100644 (file)
@@ -197,7 +197,7 @@ fn dump_path(
                 .chars()
                 .filter_map(|c| match c {
                     ' ' => None,
-                    ':' => Some('_'),
+                    ':' | '<' | '>' => Some('_'),
                     c => Some(c)
                 }));
             s
@@ -603,7 +603,8 @@ fn write_mir_sig(
     match (descr, src.promoted) {
         (_, Some(i)) => write!(w, "{:?} in ", i)?,
         (Some(Def::StructCtor(..)), _) => write!(w, "struct ")?,
-        (Some(Def::Const(_)), _) => write!(w, "const ")?,
+        (Some(Def::Const(_)), _)
+        | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
         (Some(Def::Static(_, /*is_mutbl*/false)), _) => write!(w, "static ")?,
         (Some(Def::Static(_, /*is_mutbl*/true)), _) => write!(w, "static mut ")?,
         (_, _) if is_function => write!(w, "fn ")?,
index c00f38c7db6f3a1d0ea8ab211002233ebe6440e0..20f31b3ebc1736e4c4a4244639dac1fbf62713da 100644 (file)
@@ -56,8 +56,7 @@ fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let node_id = tcx.hir().as_local_node_id(def_id)
         .expect("rvalue_promotable_map invoked with non-local def-id");
     let body_id = tcx.hir().body_owned_by(node_id);
-    let body_hir_id = tcx.hir().node_to_hir_id(body_id.node_id);
-    tcx.rvalue_promotable_map(def_id).contains(&body_hir_id.local_id)
+    tcx.rvalue_promotable_map(def_id).contains(&body_id.hir_id.local_id)
 }
 
 fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index 0681d0d80b8c9269c1f1c351974cb7425be51712..91651ad29dfa48e023beb1f65eb7cf2e9555c018 100644 (file)
@@ -805,7 +805,8 @@ fn check_field(&mut self,
                    def: &'tcx ty::AdtDef, // definition of the struct or enum
                    field: &'tcx ty::FieldDef) { // definition of the field
         let ident = Ident::new(keywords::Invalid.name(), use_ctxt);
-        let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1;
+        let current_hir = self.tcx.hir().node_to_hir_id(self.current_item);
+        let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
                              field.ident, def.variant_descr(), self.tcx.item_path_str(def.did))
index 0cabee71df9fb6ad5db1f8f408e85810b8047409..c8b3e2f4e4cf4684ff3bc1efb42efa525db5e5b1 100644 (file)
@@ -106,7 +106,15 @@ pub(crate) fn smart_resolve_report_errors(
 
         // Try to lookup name in more relaxed fashion for better error reporting.
         let ident = path.last().unwrap().ident;
-        let candidates = self.lookup_import_candidates(ident, ns, is_expected);
+        let candidates = self.lookup_import_candidates(ident, ns, is_expected)
+            .drain(..)
+            .filter(|ImportSuggestion { did, .. }| {
+                match (did, def.and_then(|def| def.opt_def_id())) {
+                    (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did,
+                    _ => true,
+                }
+            })
+            .collect::<Vec<_>>();
         if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
             let enum_candidates =
                 self.lookup_import_candidates(ident, ns, is_enum_variant);
index 6e5c0acc57026572a043dd6a7e90db09f5d543fb..fbed1145cd156089da8e95330e8a3023297cb9cc 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
-use rustc::ty;
+use rustc::ty::{self, DefIdTree};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 use rustc::{bug, span_bug};
 
@@ -92,6 +92,7 @@ enum ScopeSet {
 
 /// A free importable items suggested in case of resolution failure.
 struct ImportSuggestion {
+    did: Option<DefId>,
     path: Path,
 }
 
@@ -4391,7 +4392,8 @@ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
 
                 // collect results based on the filter function
                 if ident.name == lookup_ident.name && ns == namespace {
-                    if filter_fn(name_binding.def()) {
+                    let def = name_binding.def();
+                    if filter_fn(def) {
                         // create the path
                         let mut segms = path_segments.clone();
                         if lookup_ident.span.rust_2018() {
@@ -4415,7 +4417,12 @@ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
                         // declared as public (due to pruning, we don't explore
                         // outside crate private modules => no need to check this)
                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
-                            candidates.push(ImportSuggestion { path });
+                            let did = match def {
+                                Def::StructCtor(did, _) | Def::VariantCtor(did, _) =>
+                                    self.parent(did),
+                                _ => def.opt_def_id(),
+                            };
+                            candidates.push(ImportSuggestion { did, path });
                         }
                     }
                 }
@@ -4512,7 +4519,8 @@ fn find_module(&mut self,
                             span: name_binding.span,
                             segments: path_segments,
                         };
-                        result = Some((module, ImportSuggestion { path }));
+                        let did = module.def().and_then(|def| def.opt_def_id());
+                        result = Some((module, ImportSuggestion { did, path }));
                     } else {
                         // add the module to the lookup
                         if seen_modules.insert(module.def_id().unwrap()) {
index 8d20c44a5a4ef0c78883eefc25fb7695b4625c9a..8ab9a8e8dda86484356ea118ca322675e466888b 100644 (file)
@@ -614,11 +614,16 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
                     Some(def) if def != HirDef::Err => def,
                     _ => self.get_path_def(self.tcx.hir().get_parent_node(id)),
                 }
-            },
+            }
+
             Node::Expr(&hir::Expr {
                 node: hir::ExprKind::Struct(ref qpath, ..),
                 ..
-            }) |
+            }) => {
+                let hir_id = self.tcx.hir().node_to_hir_id(id);
+                self.tables.qpath_def(qpath, hir_id)
+            }
+
             Node::Expr(&hir::Expr {
                 node: hir::ExprKind::Path(ref qpath),
                 ..
index 5078d500679d13ed806cca0c1c4be564f0cd1d99..631966c09a498b23684277add55609c33830dd27 100644 (file)
@@ -5,7 +5,7 @@
 // UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic
 // linker is supported. As native to COFF, binaries are position-dependent, but will be relocated
 // by the loader if the pre-chosen memory location is already in use.
-// UEFI forbids running code on anything but the boot-CPU. Not interrupts are allowed other than
+// UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than
 // the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
 // code runs in the same environment, no process separation is supported.
 
@@ -21,7 +21,10 @@ pub fn opts() -> TargetOptions {
             "/NOLOGO".to_string(),
 
             // UEFI is fully compatible to non-executable data pages. Tell the compiler that
-            // non-code sections can be marked as non-executable, including stack pages.
+            // non-code sections can be marked as non-executable, including stack pages. In fact,
+            // firmware might enforce this, so we better let the linker know about this, so it
+            // will fail if the compiler ever tries placing code on the stack (e.g., trampoline
+            // constructs and alike).
             "/NXCOMPAT".to_string(),
 
             // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets
index 9ac17a1693fb5503c5aed3cb86add86a97f0ae03..443479f55f04a2361bbca5520e1ea820842587b2 100644 (file)
@@ -12,13 +12,15 @@ pub fn target() -> TargetResult {
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
 
-    // We disable MMX and SSE for now. UEFI does not prevent these from being used, but there have
-    // been reports to GRUB that some firmware does not initialize the FP exception handlers
-    // properly. Therefore, using FP coprocessors will end you up at random memory locations when
-    // you throw FP exceptions.
-    // To be safe, we disable them for now and force soft-float. This can be revisited when we
-    // have more test coverage. Disabling FP served GRUB well so far, so it should be good for us
-    // as well.
+    // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
+    // enable these CPU features explicitly before their first use, otherwise their instructions
+    // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE
+    // instruction sets, so this must be done by the firmware. However, existing firmware is known
+    // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is
+    // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so
+    // far.
+    // If you initialize FP units yourself, you can override these flags with custom linker
+    // arguments, thus giving you access to full MMX/SSE acceleration.
     base.features = "-mmx,-sse,+soft-float".to_string();
 
     // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell
@@ -26,9 +28,9 @@ pub fn target() -> TargetResult {
     // places no locality-restrictions, so it fits well here.
     base.code_model = Some("large".to_string());
 
-    // UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means
-    // small structs will be returned as int. This shouldn't matter much, since the restrictions
-    // placed by the UEFI specifications forbid any ABI to return structures.
+    // UEFI mirrors the calling-conventions used on windows. In case of x86-64 this means small
+    // structs will be returned as int. This shouldn't matter much, since the restrictions placed
+    // by the UEFI specifications forbid any ABI to return structures.
     base.abi_return_struct_as_int = true;
 
     Ok(Target {
index e4a032aaf7b18a8266b9ae751fa88c26dd8c48de..dad45130062a45a1c3d8726f55eb0b37992947cc 100644 (file)
@@ -1,6 +1,7 @@
 //! Provider for the `implied_outlives_bounds` query.
 //! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`].
 
+use rustc::hir;
 use rustc::infer::InferCtxt;
 use rustc::infer::canonical::{self, Canonical};
 use rustc::traits::{TraitEngine, TraitEngineExt};
@@ -11,7 +12,6 @@
 use rustc::ty::query::Providers;
 use rustc::ty::wf;
 use smallvec::{SmallVec, smallvec};
-use syntax::ast::DUMMY_NODE_ID;
 use syntax::source_map::DUMMY_SP;
 use rustc::traits::FulfillmentContext;
 
@@ -65,7 +65,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         // unresolved inference variables here anyway, but there might be
         // during typeck under some circumstances.)
         let obligations =
-            wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]);
+            wf::obligations(infcx, param_env, hir::DUMMY_HIR_ID, ty, DUMMY_SP).unwrap_or(vec![]);
 
         // N.B., all of these predicates *ought* to be easily proven
         // true. In fact, their correctness is (mostly) implied by
index 6fe9e316cf36ec31e092d68dcfcdfe6a9765e2c9..38f7a21e66c55fc8a5de858c3fd53968486d0f17 100644 (file)
@@ -1,3 +1,4 @@
+use rustc::hir;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution};
 use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt};
@@ -5,7 +6,6 @@
 use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use std::sync::atomic::Ordering;
-use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::DUMMY_SP;
 
 crate fn provide(p: &mut Providers<'_>) {
@@ -34,7 +34,7 @@ fn normalize_projection_ty<'tcx>(
              value: goal,
          }| {
             let selcx = &mut SelectionContext::new(infcx);
-            let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID);
+            let cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
             let mut obligations = vec![];
             let answer = traits::normalize_projection_type(
                 selcx,
index 3cc2f77187ac75c8bb6e8cb9db674290e60dda7e..30fbdbdeb443363c1fcb1654e98f9ef344aaae16 100644 (file)
@@ -1,6 +1,7 @@
 use rustc::infer::at::ToTrace;
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::InferCtxt;
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType;
 use rustc::traits::query::type_op::eq::Eq;
@@ -18,7 +19,6 @@
 };
 use rustc_data_structures::sync::Lrc;
 use std::fmt;
-use syntax::ast;
 use syntax_pos::DUMMY_SP;
 
 crate fn provide(p: &mut Providers<'_>) {
@@ -71,7 +71,7 @@ fn normalize<T>(&mut self, value: T) -> T
         self.infcx
             .partially_normalize_associated_types_in(
                 DUMMY_SP,
-                ast::CRATE_NODE_ID,
+                hir::CRATE_HIR_ID,
                 self.param_env,
                 &value,
             )
index 179350b95cb8ebef092c52ce87be831abab92b0f..23e9cd55cdce7f552fff4cfbb1cb05c07c18e61e 100644 (file)
@@ -878,8 +878,9 @@ fn ast_type_binding_to_poly_projection_predicate(
                                           binding.item_name, binding.span)
         }?;
 
+        let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id);
         let (assoc_ident, def_scope) =
-            tcx.adjust_ident(binding.item_name, candidate.def_id(), ref_id);
+            tcx.adjust_ident(binding.item_name, candidate.def_id(), hir_ref_id);
         let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| {
             i.kind == ty::AssociatedKind::Type && i.ident.modern() == assoc_ident
         }).expect("missing associated type");
@@ -1373,7 +1374,8 @@ pub fn associated_path_to_ty(
         };
 
         let trait_did = bound.def_id();
-        let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id);
+        let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id);
+        let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, hir_ref_id);
         let item = tcx.associated_items(trait_did).find(|i| {
             Namespace::from(i.kind) == Namespace::Type &&
                 i.ident.modern() == assoc_ident
index 3a670c8e2f15eca152fd121efb651ad3b2e33420..0e6ab5b1eb3b20621973fc0e8e1f4f2474b46b0a 100644 (file)
@@ -689,6 +689,8 @@ pub fn check_match(
             CoerceMany::with_coercion_sites(coerce_first, arms)
         };
 
+        let mut other_arms = vec![];  // used only for diagnostics
+        let mut prior_arm_ty = None;
         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
             if let Some(ref g) = arm.guard {
                 self.diverges.set(pats_diverge);
@@ -709,17 +711,36 @@ pub fn check_match(
                 _ => false
             };
 
+            let arm_span = if let hir::ExprKind::Block(ref blk, _) = arm.body.node {
+                // Point at the block expr instead of the entire block
+                blk.expr.as_ref().map(|e| e.span).unwrap_or(arm.body.span)
+            } else {
+                arm.body.span
+            };
             if is_if_let_fallback {
                 let cause = self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse);
                 assert!(arm_ty.is_unit());
                 coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
             } else {
-                let cause = self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
-                    arm_span: arm.body.span,
-                    source: match_src
-                });
+                let cause = if i == 0 {
+                    // The reason for the first arm to fail is not that the match arms diverge,
+                    // but rather that there's a prior obligation that doesn't hold.
+                    self.cause(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.id))
+                } else {
+                    self.cause(expr.span, ObligationCauseCode::MatchExpressionArm {
+                        arm_span,
+                        source: match_src,
+                        prior_arms: other_arms.clone(),
+                        last_ty: prior_arm_ty.unwrap(),
+                    })
+                };
                 coercion.coerce(self, &cause, &arm.body, arm_ty);
             }
+            other_arms.push(arm_span);
+            if other_arms.len() > 5 {
+                other_arms.remove(0);
+            }
+            prior_arm_ty = Some(arm_ty);
         }
 
         // We won't diverge unless the discriminant or all arms diverge.
index 35ac4f3957eb46486df0b31a01e12e42dcf7ab0b..f863cfe1887db6f9c726b2652a1668a4ddae7b9e 100644 (file)
@@ -1,6 +1,7 @@
 use super::{FnCtxt, PlaceOp, Needs};
 use super::method::MethodCallee;
 
+use rustc::hir;
 use rustc::infer::{InferCtxt, InferOk};
 use rustc::session::DiagnosticMessageId;
 use rustc::traits::{self, TraitEngine};
@@ -9,7 +10,7 @@
 use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
 
 use syntax_pos::Span;
-use syntax::ast::{self, Ident};
+use syntax::ast::Ident;
 
 use std::iter;
 
@@ -21,7 +22,7 @@ enum AutoderefKind {
 
 pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
     steps: Vec<(Ty<'tcx>, AutoderefKind)>,
     cur_ty: Ty<'tcx>,
@@ -87,7 +88,7 @@ fn next(&mut self) -> Option<Self::Item> {
 impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
                param_env: ty::ParamEnv<'tcx>,
-               body_id: ast::NodeId,
+               body_id: hir::HirId,
                span: Span,
                base_ty: Ty<'tcx>)
                -> Autoderef<'a, 'gcx, 'tcx>
index 93af07a4dd42cb900fb8bf278b3556ce1d4e97b1..722af8f0e778d16bbd85a3491977f8eabec5f42a 100644 (file)
@@ -641,7 +641,7 @@ fn closure_sigs(
             .liberate_late_bound_regions(expr_def_id, &bound_sig);
         let liberated_sig = self.inh.normalize_associated_types_in(
             body.value.span,
-            body.value.id,
+            body.value.hir_id,
             self.param_env,
             &liberated_sig,
         );
index 3b2d6d49fb2d24b915a17be5dd17a01ccbc07cb0..05ca54df2984b8eab95210201ecceb274fa33d59 100644 (file)
@@ -84,10 +84,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
     let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap();
+    let impl_m_hir_id = tcx.hir().node_to_hir_id(impl_m_node_id);
 
     let cause = ObligationCause {
         span: impl_m_span,
-        body_id: impl_m_node_id,
+        body_id: impl_m_hir_id,
         code: ObligationCauseCode::CompareImplMethodObligation {
             item_name: impl_m.ident.name,
             impl_item_def_id: impl_m.def_id,
@@ -205,7 +206,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Construct trait parameter environment and then shift it into the placeholder viewpoint.
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
-    let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
+    let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
     let param_env = ty::ParamEnv::new(
         tcx.intern_predicates(&hybrid_preds.predicates),
         Reveal::UserFacing,
@@ -262,7 +263,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
-                                              impl_m_node_id,
+                                              impl_m_hir_id,
                                               param_env,
                                               &impl_sig);
         let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig));
@@ -275,7 +276,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             trait_sig.subst(tcx, trait_to_skol_substs);
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span,
-                                              impl_m_node_id,
+                                              impl_m_hir_id,
                                               param_env,
                                               &trait_sig);
         let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig));
@@ -347,8 +348,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let fcx = FnCtxt::new(&inh, param_env, impl_m_node_id);
-        fcx.regionck_item(impl_m_node_id, impl_m_span, &[]);
+        let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
+        fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]);
 
         Ok(())
     })
@@ -903,22 +904,23 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Create a parameter environment that represents the implementation's
         // method.
         let impl_c_node_id = tcx.hir().as_local_node_id(impl_c.def_id).unwrap();
+        let impl_c_hir_id = tcx.hir().node_to_hir_id(impl_c_node_id);
 
         // Compute placeholder form of impl and trait const tys.
         let impl_ty = tcx.type_of(impl_c.def_id);
         let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
-        let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
+        let mut cause = ObligationCause::misc(impl_c_span, impl_c_hir_id);
 
         // There is no "body" here, so just pass dummy id.
         let impl_ty = inh.normalize_associated_types_in(impl_c_span,
-                                                        impl_c_node_id,
+                                                        impl_c_hir_id,
                                                         param_env,
                                                         &impl_ty);
 
         debug!("compare_const_impl: impl_ty={:?}", impl_ty);
 
         let trait_ty = inh.normalize_associated_types_in(impl_c_span,
-                                                         impl_c_node_id,
+                                                         impl_c_hir_id,
                                                          param_env,
                                                          &trait_ty);
 
@@ -973,7 +975,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             return;
         }
 
-        let fcx = FnCtxt::new(&inh, param_env, impl_c_node_id);
-        fcx.regionck_item(impl_c_node_id, impl_c_span, &[]);
+        let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
+        fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
     });
 }
index 33e93b582e5401bc40a7c48918c85dae53c891a0..8b80fba4d19d01e096b72c3d5a033a5f9c442f09 100644 (file)
@@ -210,7 +210,10 @@ fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
     /// ```
     /// opt.map(|arg| { takes_ref(arg) });
     /// ```
-    fn can_use_as_ref(&self, expr: &hir::Expr) -> Option<(Span, &'static str, String)> {
+    fn can_use_as_ref(
+        &self,
+        expr: &hir::Expr,
+    ) -> Option<(Span, &'static str, String)> {
         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
             if let hir::def::Def::Local(id) = path.def {
                 let parent = self.tcx.hir().get_parent_node(id);
@@ -233,10 +236,12 @@ fn can_use_as_ref(&self, expr: &hir::Expr) -> Option<(Span, &'static str, String
                             self_ty.starts_with("std::option::Option") ||
                             self_ty.starts_with("std::result::Result")
                         ) && (name == "map" || name == "and_then");
-                        if is_as_ref_able {
-                            return Some((span.shrink_to_lo(),
-                                         "consider using `as_ref` instead",
-                                         "as_ref().".into()));
+                        match (is_as_ref_able, self.sess().source_map().span_to_snippet(*span)) {
+                            (true, Ok(src)) => {
+                                return Some((*span, "consider using `as_ref` instead",
+                                             format!("as_ref().{}", src)));
+                            },
+                            _ => ()
                         }
                     }
                 }
@@ -430,7 +435,11 @@ fn is_range_literal(&self, expr: &hir::Expr) -> bool {
 
         match expr.node {
             // All built-in range literals but `..=` and `..` desugar to Structs
-            ExprKind::Struct(QPath::Resolved(None, ref path), _, _) |
+            ExprKind::Struct(ref qpath, _, _) => {
+                if let QPath::Resolved(None, ref path) = **qpath {
+                    return is_range_path(&path) && span_is_range_literal(&expr.span);
+                }
+            }
             // `..` desugars to its struct path
             ExprKind::Path(QPath::Resolved(None, ref path)) => {
                 return is_range_path(&path) && span_is_range_literal(&expr.span);
index 5c2608e36163b2cfcf9a773a06f496dffb32a7f8..ad74e78fecdcdb1270e7b743975cc57b6be0bd79 100644 (file)
@@ -1,5 +1,6 @@
 use crate::check::regionck::RegionCtxt;
 
+use crate::hir;
 use crate::hir::def_id::DefId;
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::infer::{self, InferOk, SuppressRegionErrors};
@@ -9,7 +10,6 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use crate::util::common::ErrorReported;
 
-use syntax::ast;
 use syntax_pos::Span;
 
 /// This function confirms that the `Drop` implementation identified by
@@ -70,7 +70,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
     drop_impl_ty: Ty<'tcx>,
     self_type_did: DefId,
 ) -> Result<(), ErrorReported> {
-    let drop_impl_node_id = tcx.hir().as_local_node_id(drop_impl_did).unwrap();
+    let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did).unwrap();
 
     // check that the impl type can be made to match the trait type.
 
@@ -85,7 +85,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
         let fresh_impl_substs = infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
         let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
 
-        let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id);
+        let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
         match infcx
             .at(cause, impl_param_env)
             .eq(named_type, fresh_impl_self_ty)
@@ -291,7 +291,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
     rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
     ty: Ty<'tcx>,
     span: Span,
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
     scope: region::Scope,
 ) -> Result<(), ErrorReported> {
     debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
index 43513a83b6c89f8316b487236e59cc19e1b9111b..fca9fa0829f7263e6e9f255ff00761b10c4e753a 100644 (file)
@@ -58,7 +58,7 @@ fn equate_intrinsic_type<'a, 'tcx>(
         safety,
         abi
     )));
-    let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
+    let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType);
     require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
 }
 
index fd93fea00bcf503b368b4a573ffe0e70637fe988..709177212ada7409e2824b367f9684cf9790d400 100644 (file)
@@ -401,7 +401,7 @@ fn method_autoderef_steps<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| {
         let ParamEnvAnd { param_env, value: self_ty } = goal;
 
-        let mut autoderef = Autoderef::new(infcx, param_env, ast::DUMMY_NODE_ID, DUMMY_SP, self_ty)
+        let mut autoderef = Autoderef::new(infcx, param_env, hir::DUMMY_HIR_ID, DUMMY_SP, self_ty)
             .include_raw_pointers()
             .silence_errors();
         let mut reached_raw_pointer = false;
@@ -1183,7 +1183,7 @@ fn emit_unstable_name_collision_hint(
         stable_pick: &Pick,
         unstable_candidates: &[(&Candidate<'tcx>, Symbol)],
     ) {
-        let mut diag = self.tcx.struct_span_lint_node(
+        let mut diag = self.tcx.struct_span_lint_hir(
             lint::builtin::UNSTABLE_NAME_COLLISIONS,
             self.fcx.body_id,
             self.span,
index aa6f73b29b4b585fddbf6254242e3f16cbd17f58..768842ef39214f0e5dc817212e925e8ac356c000 100644 (file)
@@ -346,7 +346,8 @@ pub fn report_method_error<'b>(&self,
                                     };
 
                                     let field_ty = field.ty(tcx, substs);
-                                    let scope = self.tcx.hir().get_module_parent(self.body_id);
+                                    let scope = self.tcx.hir().get_module_parent_by_hir_id(
+                                        self.body_id);
                                     if field.vis.is_accessible_from(scope, self.tcx) {
                                         if self.is_fn_ty(&field_ty, span) {
                                             err.help(&format!("use `({0}.{1})(...)` if you \
@@ -499,7 +500,7 @@ fn suggest_use_candidates(&self,
                               err: &mut DiagnosticBuilder,
                               mut msg: String,
                               candidates: Vec<DefId>) {
-        let module_did = self.tcx.hir().get_module_parent(self.body_id);
+        let module_did = self.tcx.hir().get_module_parent_by_hir_id(self.body_id);
         let module_id = self.tcx.hir().as_local_node_id(module_did).unwrap();
         let krate = self.tcx.hir().krate();
         let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
@@ -752,12 +753,11 @@ fn handle_external_def(tcx: TyCtxt,
                            traits: &mut Vec<DefId>,
                            external_mods: &mut FxHashSet<DefId>,
                            def: Def) {
-        let def_id = def.def_id();
         match def {
-            Def::Trait(..) => {
+            Def::Trait(def_id) => {
                 traits.push(def_id);
             }
-            Def::Mod(..) => {
+            Def::Mod(def_id) => {
                 if !external_mods.insert(def_id) {
                     return;
                 }
index acaa3d39662880e9be315520d69ae86ce250bf78..91e44a15882684f3e463b5e1feef378f8110ee60 100644 (file)
@@ -510,7 +510,7 @@ fn find_breakable(&mut self, target_id: ast::NodeId) -> &mut BreakableCtxt<'gcx,
 }
 
 pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
 
     /// The parameter environment used for proving trait obligations
     /// in this function. This can change when we descend into
@@ -672,7 +672,7 @@ fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T {
 
     fn normalize_associated_types_in<T>(&self,
                                         span: Span,
-                                        body_id: ast::NodeId,
+                                        body_id: hir::HirId,
                                         param_env: ty::ParamEnv<'tcx>,
                                         value: &T) -> T
         where T : TypeFoldable<'tcx>
@@ -861,14 +861,14 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 tcx.liberate_late_bound_regions(def_id, &fn_sig);
             let fn_sig =
                 inh.normalize_associated_types_in(body.value.span,
-                                                  body_id.node_id,
+                                                  body_id.hir_id,
                                                   param_env,
                                                   &fn_sig);
 
             let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
             fcx
         } else {
-            let fcx = FnCtxt::new(&inh, param_env, body.value.id);
+            let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
             let expected_type = tcx.type_of(def_id);
             let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
             fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
@@ -1062,7 +1062,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Create the function context.  This is either derived from scratch or,
     // in the case of closures, based on the outer context.
-    let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
+    let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
     *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
 
     let declared_ret_ty = fn_sig.output();
@@ -1169,8 +1169,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                 let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
                 let trait_ref = ty::TraitRef::new(term_id, substs);
                 let return_ty_span = decl.output.span();
+                let fn_hir_id = fcx.tcx.hir().node_to_hir_id(fn_id);
                 let cause = traits::ObligationCause::new(
-                    return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
+                    return_ty_span, fn_hir_id, ObligationCauseCode::MainFunctionType);
 
                 inherited.register_predicate(
                     traits::Obligation::new(
@@ -2022,7 +2023,7 @@ enum TupleArgumentsFlag {
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
                param_env: ty::ParamEnv<'tcx>,
-               body_id: ast::NodeId)
+               body_id: hir::HirId)
                -> FnCtxt<'a, 'gcx, 'tcx> {
         FnCtxt {
             body_id,
index 79ade3bb5a65a7306068ea21f7ee3f0f02127cd1..792f8eaacd29031d9d1a1eb8cf8d94529a697727 100644 (file)
@@ -112,7 +112,7 @@ macro_rules! ignore_err {
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn regionck_expr(&self, body: &'gcx hir::Body) {
         let subject = self.tcx.hir().body_owner_def_id(body.id());
-        let id = body.value.id;
+        let id = body.value.hir_id;
         let mut rcx = RegionCtxt::new(
             self,
             RepeatingScope(id),
@@ -138,9 +138,9 @@ pub fn regionck_expr(&self, body: &'gcx hir::Body) {
 
     /// Region checking during the WF phase for items. `wf_tys` are the
     /// types from which we should derive implied bounds, if any.
-    pub fn regionck_item(&self, item_id: ast::NodeId, span: Span, wf_tys: &[Ty<'tcx>]) {
+    pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
         debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
-        let subject = self.tcx.hir().local_def_id(item_id);
+        let subject = self.tcx.hir().local_def_id_from_hir_id(item_id);
         let mut rcx = RegionCtxt::new(
             self,
             RepeatingScope(item_id),
@@ -166,18 +166,19 @@ pub fn regionck_item(&self, item_id: ast::NodeId, span: Span, wf_tys: &[Ty<'tcx>
     pub fn regionck_fn(&self, fn_id: ast::NodeId, body: &'gcx hir::Body) {
         debug!("regionck_fn(id={})", fn_id);
         let subject = self.tcx.hir().body_owner_def_id(body.id());
-        let node_id = body.value.id;
+        let hir_id = body.value.hir_id;
         let mut rcx = RegionCtxt::new(
             self,
-            RepeatingScope(node_id),
-            node_id,
+            RepeatingScope(hir_id),
+            hir_id,
             Subject(subject),
             self.param_env,
         );
 
         if self.err_count_since_creation() == 0 {
+            let fn_hir_id = self.tcx.hir().node_to_hir_id(fn_id);
             // regionck assumes typeck succeeded
-            rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
+            rcx.visit_fn_body(fn_hir_id, body, self.tcx.hir().span_by_hir_id(fn_hir_id));
         }
 
         rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
@@ -201,13 +202,13 @@ pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     outlives_environment: OutlivesEnvironment<'tcx>,
 
     // id of innermost fn body id
-    body_id: ast::NodeId,
+    body_id: hir::HirId,
 
     // call_site scope of innermost fn
     call_site_scope: Option<region::Scope>,
 
     // id of innermost fn or loop
-    repeating_scope: ast::NodeId,
+    repeating_scope: hir::HirId,
 
     // id of AST node being analyzed (the subject of the analysis).
     subject_def_id: DefId,
@@ -220,14 +221,14 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-pub struct RepeatingScope(ast::NodeId);
+pub struct RepeatingScope(hir::HirId);
 pub struct Subject(DefId);
 
 impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     pub fn new(
         fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
         RepeatingScope(initial_repeating_scope): RepeatingScope,
-        initial_body_id: ast::NodeId,
+        initial_body_id: hir::HirId,
         Subject(subject): Subject,
         param_env: ty::ParamEnv<'tcx>,
     ) -> RegionCtxt<'a, 'gcx, 'tcx> {
@@ -244,7 +245,7 @@ pub fn new(
         }
     }
 
-    fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
+    fn set_repeating_scope(&mut self, scope: hir::HirId) -> hir::HirId {
         mem::replace(&mut self.repeating_scope, scope)
     }
 
@@ -301,15 +302,15 @@ pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
     /// `intravisit::Visitor` impl below.)
     fn visit_fn_body(
         &mut self,
-        id: ast::NodeId, // the id of the fn itself
+        id: hir::HirId, // the id of the fn itself
         body: &'gcx hir::Body,
         span: Span,
     ) {
         // When we enter a function, we can derive
-        debug!("visit_fn_body(id={})", id);
+        debug!("visit_fn_body(id={:?})", id);
 
         let body_id = body.id();
-        self.body_id = body_id.node_id;
+        self.body_id = body_id.hir_id;
 
         let call_site = region::Scope {
             id: body.value.hir_id.local_id,
@@ -318,11 +319,10 @@ fn visit_fn_body(
         self.call_site_scope = Some(call_site);
 
         let fn_sig = {
-            let fn_hir_id = self.tcx.hir().node_to_hir_id(id);
-            match self.tables.borrow().liberated_fn_sigs().get(fn_hir_id) {
+            match self.tables.borrow().liberated_fn_sigs().get(id) {
                 Some(f) => f.clone(),
                 None => {
-                    bug!("No fn-sig entry for id={}", id);
+                    bug!("No fn-sig entry for id={:?}", id);
                 }
             }
         };
@@ -342,11 +342,11 @@ fn visit_fn_body(
         self.outlives_environment.add_implied_bounds(
             self.fcx,
             &fn_sig_tys[..],
-            body_id.node_id,
+            body_id.hir_id,
             span,
         );
         self.outlives_environment
-            .save_implied_bounds(body_id.node_id);
+            .save_implied_bounds(body_id.hir_id);
         self.link_fn_args(
             region::Scope {
                 id: body.value.hir_id.local_id,
@@ -355,7 +355,7 @@ fn visit_fn_body(
             &body.arguments,
         );
         self.visit_body(body);
-        self.visit_region_obligations(body_id.node_id);
+        self.visit_region_obligations(body_id.hir_id);
 
         let call_site_scope = self.call_site_scope.unwrap();
         debug!(
@@ -365,8 +365,7 @@ fn visit_fn_body(
         );
         let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
 
-        let body_hir_id = self.tcx.hir().node_to_hir_id(body_id.node_id);
-        self.type_of_node_must_outlive(infer::CallReturn(span), body_hir_id, call_site_region);
+        self.type_of_node_must_outlive(infer::CallReturn(span), body_id.hir_id, call_site_region);
 
         self.constrain_opaque_types(
             &self.fcx.opaque_types.borrow(),
@@ -374,8 +373,8 @@ fn visit_fn_body(
         );
     }
 
-    fn visit_region_obligations(&mut self, node_id: ast::NodeId) {
-        debug!("visit_region_obligations: node_id={}", node_id);
+    fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
+        debug!("visit_region_obligations: hir_id={:?}", hir_id);
 
         // region checking can introduce new pending obligations
         // which, when processed, might generate new region
@@ -474,7 +473,8 @@ fn visit_fn(
         let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
 
         let body = self.tcx.hir().body(body_id);
-        self.visit_fn_body(id, body, span);
+        let hir_id = self.tcx.hir().node_to_hir_id(id);
+        self.visit_fn_body(hir_id, body, span);
 
         // Restore state from previous function.
         self.outlives_environment
@@ -502,7 +502,7 @@ fn visit_local(&mut self, l: &'gcx hir::Local) {
 
     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         debug!(
-            "regionck::visit_expr(e={:?}, repeating_scope={})",
+            "regionck::visit_expr(e={:?}, repeating_scope={:?})",
             expr, self.repeating_scope
         );
 
@@ -555,7 +555,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         }
 
         debug!(
-            "regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
+            "regionck::visit_expr(e={:?}, repeating_scope={:?}) - visiting subexprs",
             expr, self.repeating_scope
         );
         match expr.node {
@@ -679,16 +679,16 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
             }
 
             hir::ExprKind::Loop(ref body, _, _) => {
-                let repeating_scope = self.set_repeating_scope(body.id);
+                let repeating_scope = self.set_repeating_scope(body.hir_id);
                 intravisit::walk_expr(self, expr);
                 self.set_repeating_scope(repeating_scope);
             }
 
             hir::ExprKind::While(ref cond, ref body, _) => {
-                let repeating_scope = self.set_repeating_scope(cond.id);
+                let repeating_scope = self.set_repeating_scope(cond.hir_id);
                 self.visit_expr(&cond);
 
-                self.set_repeating_scope(body.id);
+                self.set_repeating_scope(body.hir_id);
                 self.visit_block(&body);
 
                 self.set_repeating_scope(repeating_scope);
@@ -758,7 +758,7 @@ fn walk_cast(&mut self, cast_expr: &hir::Expr, from_ty: Ty<'tcx>, to_ty: Ty<'tcx
     }
 
     fn check_expr_fn_block(&mut self, expr: &'gcx hir::Expr, body_id: hir::BodyId) {
-        let repeating_scope = self.set_repeating_scope(body_id.node_id);
+        let repeating_scope = self.set_repeating_scope(body_id.hir_id);
         intravisit::walk_expr(self, expr);
         self.set_repeating_scope(repeating_scope);
     }
index 1489ebac748f162b21c35568884a2cdb27fba4f2..86b2e0bfe8aef6d9a96b51f61aec50baa5239b05 100644 (file)
@@ -22,7 +22,7 @@
 /// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
-    id: ast::NodeId,
+    id: hir::HirId,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -226,9 +226,10 @@ fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
 fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
                           -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
     let def_id = tcx.hir().local_def_id(id);
+    let hir_id = tcx.hir().node_to_hir_id(id);
     CheckWfFcxBuilder {
         inherited: Inherited::build(tcx, def_id),
-        id,
+        id: hir_id,
         span,
         param_env: tcx.param_env(def_id),
     }
@@ -968,13 +969,13 @@ fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
 fn check_false_global_bounds<'a, 'gcx, 'tcx>(
     fcx: &FnCtxt<'a, 'gcx, 'tcx>,
     span: Span,
-    id: ast::NodeId)
+    id: hir::HirId)
 {
     use rustc::ty::TypeFoldable;
 
     let empty_env = ty::ParamEnv::empty();
 
-    let def_id = fcx.tcx.hir().local_def_id(id);
+    let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);
     let predicates = fcx.tcx.predicates_of(def_id).predicates
         .iter()
         .map(|(p, _)| *p)
index e02e70651d6c130d26e306a9975a843890293308..e68c50d752bd5d78c07f71605f6f1191d050587f 100644 (file)
@@ -100,7 +100,7 @@ fn new(
         body: &'gcx hir::Body,
         rustc_dump_user_substs: bool,
     ) -> WritebackCx<'cx, 'gcx, 'tcx> {
-        let owner = fcx.tcx.hir().definitions().node_to_hir_id(body.id().node_id);
+        let owner = body.id().hir_id;
 
         WritebackCx {
             fcx,
index 3ec08f221f576e98b13f30d84bf0bcf00cf810d6..0996d1ff3b9989f2377b2f5396415ea208061682 100644 (file)
@@ -162,8 +162,8 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
     if impl_did.is_local() {
         let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap();
 
-        let impl_node_id = tcx.hir().as_local_node_id(impl_did).unwrap();
-        let span = tcx.hir().span(impl_node_id);
+        let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).unwrap();
+        let span = tcx.hir().span_by_hir_id(impl_hir_id);
 
         let source = tcx.type_of(impl_did);
         assert!(!source.has_escaping_bound_vars());
@@ -185,7 +185,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
         };
 
         tcx.infer_ctxt().enter(|infcx| {
-            let cause = ObligationCause::misc(span, impl_node_id);
+            let cause = ObligationCause::misc(span, impl_hir_id);
 
             use ty::TyKind::*;
             match (&source.sty, &target.sty) {
@@ -332,7 +332,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
     });
 
     // this provider should only get invoked for local def-ids
-    let impl_node_id = gcx.hir().as_local_node_id(impl_did).unwrap_or_else(|| {
+    let impl_hir_id = gcx.hir().as_local_hir_id(impl_did).unwrap_or_else(|| {
         bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
     });
 
@@ -344,7 +344,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
            source,
            target);
 
-    let span = gcx.hir().span(impl_node_id);
+    let span = gcx.hir().span_by_hir_id(impl_hir_id);
     let param_env = gcx.param_env(impl_did);
     assert!(!source.has_escaping_bound_vars());
 
@@ -355,7 +355,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
            target);
 
     gcx.infer_ctxt().enter(|infcx| {
-        let cause = ObligationCause::misc(span, impl_node_id);
+        let cause = ObligationCause::misc(span, impl_hir_id);
         let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>,
                            mt_b: ty::TypeAndMut<'gcx>,
                            mk_ptr: &dyn Fn(Ty<'gcx>) -> Ty<'gcx>| {
@@ -481,11 +481,11 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                being coerced, none found");
                     return err_info;
                 } else if diff_fields.len() > 1 {
-                    let item = gcx.hir().expect_item(impl_node_id);
+                    let item = gcx.hir().expect_item_by_hir_id(impl_hir_id);
                     let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.node {
                         t.path.span
                     } else {
-                        gcx.hir().span(impl_node_id)
+                        gcx.hir().span_by_hir_id(impl_hir_id)
                     };
 
                     let mut err = struct_span_err!(gcx.sess,
@@ -527,7 +527,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
         let mut fulfill_cx = TraitEngine::new(infcx.tcx);
 
         // Register an obligation for `A: Trait<B>`.
-        let cause = traits::ObligationCause::misc(span, impl_node_id);
+        let cause = traits::ObligationCause::misc(span, impl_hir_id);
         let predicate = gcx.predicate_for_trait_def(param_env,
                                                     cause,
                                                     trait_def_id,
index e6533ac4b75598586fd0bce26524750390fc5136..71767fcfd49339ad5256d7c9b8a0e45209fe21d7 100644 (file)
@@ -1,3 +1,4 @@
+// ignore-tidy-linelength
 #![allow(non_snake_case)]
 
 register_long_diagnostics! {
@@ -1544,7 +1545,9 @@ fn f<T>() {}
 
 It is not possible to declare type parameters on a function that has the `start`
 attribute. Such a function must have the following type signature (for more
-information: http://doc.rust-lang.org/stable/book/first-edition/no-stdlib.html):
+information, view [the unstable book][1]):
+
+[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
 
 ```
 # let _:
@@ -2918,10 +2921,11 @@ impl Baz for Bar { } // Note: This is OK
 
 E0374: r##"
 A struct without a field containing an unsized type cannot implement
-`CoerceUnsized`. An
-[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html)
-is any type that the compiler doesn't know the length or alignment of at
-compile time. Any struct containing an unsized type is also unsized.
+`CoerceUnsized`. An [unsized type][1] is any type that the compiler
+doesn't know the length or alignment of at compile time. Any struct
+containing an unsized type is also unsized.
+
+[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
 
 Example of erroneous code:
 
@@ -2978,9 +2982,9 @@ impl<T, U> CoerceUnsized<Bar<U>> for Bar<T>
 `CoerceUnsized`. This only occurs when you are trying to coerce one of the
 types in your struct to another type in the struct. In this case we try to
 impl `CoerceUnsized` from `T` to `U` which are both types that the struct
-takes. An [unsized type] is any type that the compiler doesn't know the length
-or alignment of at compile time. Any struct containing an unsized type is also
-unsized.
+takes. An [unsized type][1] is any type that the compiler doesn't know the
+length or alignment of at compile time. Any struct containing an unsized type
+is also unsized.
 
 Example of erroneous code:
 
@@ -3025,7 +3029,7 @@ fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
 }
 ```
 
-[unsized type]: https://doc.rust-lang.org/book/first-edition/unsized-types.html
+[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
 "##,
 
 E0376: r##"
@@ -3033,11 +3037,12 @@ fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
 `CoerceUnsized` can only be implemented for a struct. Unsized types are
 already able to be coerced without an implementation of `CoerceUnsized`
 whereas a struct containing an unsized type needs to know the unsized type
-field it's containing is able to be coerced. An
-[unsized type](https://doc.rust-lang.org/book/first-edition/unsized-types.html)
+field it's containing is able to be coerced. An [unsized type][1]
 is any type that the compiler doesn't know the length or alignment of at
 compile time. Any struct containing an unsized type is also unsized.
 
+[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
+
 Example of erroneous code:
 
 ```compile_fail,E0376
@@ -3883,8 +3888,10 @@ trait was performed.
 assert_eq!(c, 'V');
 ```
 
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+For more information about casts, take a look at the Type cast section in
+[The Reference Book][1].
+
+[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
 "##,
 
 E0605: r##"
@@ -3912,8 +3919,10 @@ trait was performed.
 v as *const i8; // ok!
 ```
 
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+For more information about casts, take a look at the Type cast section in
+[The Reference Book][1].
+
+[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
 "##,
 
 E0606: r##"
@@ -3934,8 +3943,10 @@ trait was performed.
 let y: u32 = *x as u32; // We dereference it first and then cast it.
 ```
 
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+For more information about casts, take a look at the Type cast section in
+[The Reference Book][1].
+
+[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
 "##,
 
 E0607: r##"
@@ -3961,8 +3972,10 @@ trait was performed.
 
 To fix this error, don't try to cast directly between thin and fat pointers.
 
-For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+For more information about casts, take a look at the Type cast section in
+[The Reference Book][1].
+
+[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions
 "##,
 
 E0609: r##"
@@ -4020,8 +4033,8 @@ struct Foo {
 ```
 
 For more information about primitives and structs, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/primitive-types.html
-https://doc.rust-lang.org/book/first-edition/structs.html
+https://doc.rust-lang.org/book/ch03-02-data-types.html
+https://doc.rust-lang.org/book/ch05-00-structs.html
 "##,
 
 E0614: r##"
index 931621fb53701b5bd300abd22dadee42e92825f1..7055218577c5c8accb30895dbbff87adb7d455c0 100644 (file)
@@ -179,12 +179,12 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
-    let main_id = tcx.hir().as_local_node_id(main_def_id).unwrap();
+    let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
     let main_span = tcx.def_span(main_def_id);
     let main_t = tcx.type_of(main_def_id);
     match main_t.sty {
         ty::FnDef(..) => {
-            if let Some(Node::Item(it)) = tcx.hir().find(main_id) {
+            if let Some(Node::Item(it)) = tcx.hir().find_by_hir_id(main_id) {
                 if let hir::ItemKind::Fn(.., ref generics, _) = it.node {
                     let mut error = false;
                     if !generics.params.is_empty() {
@@ -244,12 +244,12 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
 }
 
 fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) {
-    let start_id = tcx.hir().as_local_node_id(start_def_id).unwrap();
+    let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
     let start_span = tcx.def_span(start_def_id);
     let start_t = tcx.type_of(start_def_id);
     match start_t.sty {
         ty::FnDef(..) => {
-            if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
+            if let Some(Node::Item(it)) = tcx.hir().find_by_hir_id(start_id) {
                 if let hir::ItemKind::Fn(.., ref generics, _) = it.node {
                     let mut error = false;
                     if !generics.params.is_empty() {
index f75ab47e1ab70d14599d6f4653f9c10ecddb9205..3e3eab8cf4cfb2e19315195d1927c82f3bdbfad1 100644 (file)
@@ -137,7 +137,7 @@ fn extended(&self, mut err: DiagnosticBuilder<'tcx>) -> DiagnosticBuilder<'tcx>
 pointers.
 
 For more information about casts, take a look at The Book:
-https://doc.rust-lang.org/book/first-edition/casting-between-types.html");
+https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions");
         err
     }
 }
index 8dab9efa36c62d65a23db7fad61a4b049aff3b8b..d12b5021ca9fae5902c5fe3fbdfd0d7bc8939c6e 100644 (file)
@@ -3830,7 +3830,7 @@ fn print_const(cx: &DocContext, n: ty::LazyConst) -> String {
 }
 
 fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
-    cx.tcx.hir().node_to_pretty_string(body.node_id)
+    cx.tcx.hir().hir_to_pretty_string(body.hir_id)
 }
 
 /// Given a type Path, resolve it to a Type using the TyCtxt
index 1618307e4839a435c4151dc9c8a7ee89b0fceff0..e660d27d74b4cf416cb7ababd012da123d5fa8c8 100644 (file)
@@ -2823,7 +2823,17 @@ fn tag_html(class: &str, contents: &str) -> String {
 
     // The trailing space after each tag is to space it properly against the rest of the docs.
     if item.deprecation().is_some() {
-        tags += &tag_html("deprecated", "Deprecated");
+        let mut message = "Deprecated";
+        if let Some(ref stab) = item.stability {
+            if let Some(ref depr) = stab.deprecation {
+                if let Some(ref since) = depr.since {
+                    if !stability::deprecation_in_effect(&since) {
+                        message = "Deprecation planned";
+                    }
+                }
+            }
+        }
+        tags += &tag_html("deprecated", message);
     }
 
     if let Some(stab) = item
@@ -2851,16 +2861,23 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
     let mut stability = vec![];
     let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
 
-    if let Some(Deprecation { since, note }) = &item.deprecation() {
+    if let Some(Deprecation { note, since }) = &item.deprecation() {
+        // We display deprecation messages for #[deprecated] and #[rustc_deprecated]
+        // but only display the future-deprecation messages for #[rustc_deprecated].
         let mut message = if let Some(since) = since {
-            if stability::deprecation_in_effect(since) {
-                format!("Deprecated since {}", Escape(since))
-            } else {
-                format!("Deprecating in {}", Escape(since))
-            }
+            format!("Deprecated since {}", Escape(since))
         } else {
             String::from("Deprecated")
         };
+        if let Some(ref stab) = item.stability {
+            if let Some(ref depr) = stab.deprecation {
+                if let Some(ref since) = depr.since {
+                    if !stability::deprecation_in_effect(&since) {
+                        message = format!("Deprecating in {}", Escape(&since));
+                    }
+                }
+            }
+        }
 
         if let Some(note) = note {
             let mut ids = cx.id_map.borrow_mut();
index 7413a917f056325c9a457e4a24f970c51ff753f5..bd5cae861e93b4228e954d3f5955754fa25d66b8 100644 (file)
@@ -60,9 +60,11 @@ pub fn visit_mod(&mut self, def_id: DefId) {
         }
 
         for item in self.cx.tcx.item_children(def_id).iter() {
-            if self.cx.tcx.def_key(item.def.def_id()).parent.map_or(false, |d| d == def_id.index) ||
-                item.vis == Visibility::Public {
-                self.visit_item(item.def);
+            if let Some(def_id) = item.def.opt_def_id() {
+                if self.cx.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) ||
+                    item.vis == Visibility::Public {
+                    self.visit_item(item.def);
+                }
             }
         }
     }
index d1203be3cf011b10d486eac66ea850565a9bcf81..aa784746122db71e82ccc8896d491d67a2587333 100644 (file)
@@ -5,7 +5,7 @@
 use core::pin::Pin;
 use core::option::Option;
 use core::ptr::NonNull;
-use core::task::{LocalWaker, Poll};
+use core::task::{Waker, Poll};
 use core::ops::{Drop, Generator, GeneratorState};
 
 #[doc(inline)]
@@ -32,10 +32,10 @@ impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
 #[unstable(feature = "gen_future", issue = "50547")]
 impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
     type Output = T::Return;
-    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
         // Safe because we're !Unpin + !Drop mapping to a ?Unpin value
         let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-        set_task_waker(lw, || match gen.resume() {
+        set_task_waker(waker, || match gen.resume() {
             GeneratorState::Yielded(()) => Poll::Pending,
             GeneratorState::Complete(x) => Poll::Ready(x),
         })
@@ -43,10 +43,10 @@ fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
 }
 
 thread_local! {
-    static TLS_WAKER: Cell<Option<NonNull<LocalWaker>>> = Cell::new(None);
+    static TLS_WAKER: Cell<Option<NonNull<Waker>>> = Cell::new(None);
 }
 
-struct SetOnDrop(Option<NonNull<LocalWaker>>);
+struct SetOnDrop(Option<NonNull<Waker>>);
 
 impl Drop for SetOnDrop {
     fn drop(&mut self) {
@@ -58,12 +58,12 @@ fn drop(&mut self) {
 
 #[unstable(feature = "gen_future", issue = "50547")]
 /// Sets the thread-local task context used by async/await futures.
-pub fn set_task_waker<F, R>(lw: &LocalWaker, f: F) -> R
+pub fn set_task_waker<F, R>(waker: &Waker, f: F) -> R
 where
     F: FnOnce() -> R
 {
     let old_waker = TLS_WAKER.with(|tls_waker| {
-        tls_waker.replace(Some(NonNull::from(lw)))
+        tls_waker.replace(Some(NonNull::from(waker)))
     });
     let _reset_waker = SetOnDrop(old_waker);
     f()
@@ -78,7 +78,7 @@ pub fn set_task_waker<F, R>(lw: &LocalWaker, f: F) -> R
 /// retrieved by a surrounding call to get_task_waker.
 pub fn get_task_waker<F, R>(f: F) -> R
 where
-    F: FnOnce(&LocalWaker) -> R
+    F: FnOnce(&Waker) -> R
 {
     let waker_ptr = TLS_WAKER.with(|tls_waker| {
         // Clear the entry so that nested `get_task_waker` calls
@@ -88,7 +88,7 @@ pub fn get_task_waker<F, R>(f: F) -> R
     let _reset_waker = SetOnDrop(waker_ptr);
 
     let waker_ptr = waker_ptr.expect(
-        "TLS LocalWaker not set. This is a rustc bug. \
+        "TLS Waker not set. This is a rustc bug. \
         Please file an issue on https://github.com/rust-lang/rust.");
     unsafe { f(waker_ptr.as_ref()) }
 }
@@ -99,5 +99,5 @@ pub fn poll_with_tls_waker<F>(f: Pin<&mut F>) -> Poll<F::Output>
 where
     F: Future
 {
-    get_task_waker(|lw| F::poll(f, lw))
+    get_task_waker(|waker| F::poll(f, waker))
 }
index 63cf6b62145a9a32aac7ac2a6f4fa27959fbded3..4f900e8cbad2d17be96337255645854191900459 100644 (file)
 #[cfg(test)] extern crate std as realstd;
 
 #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
-#[macro_use]
-#[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot
-                         // determine resolution for the macro `usercalls_asm`”
 extern crate fortanix_sgx_abi;
 
 // The standard macros that are not built-in to the compiler.
@@ -466,8 +463,6 @@ pub mod task {
     //! Types and Traits for working with asynchronous tasks.
     #[doc(inline)]
     pub use core::task::*;
-    #[doc(inline)]
-    pub use alloc_crate::task::*;
 }
 
 #[unstable(feature = "futures_api",
index d27f6ca88c2e945bbd80055b9f101dbb686d83ad..862fdf051ccd10b1d6344c4802c18ed94246fba5 100644 (file)
@@ -12,7 +12,7 @@
 use ptr::{Unique, NonNull};
 use rc::Rc;
 use sync::{Arc, Mutex, RwLock, atomic};
-use task::{LocalWaker, Poll};
+use task::{Waker, Poll};
 use thread::Result;
 
 #[stable(feature = "panic_hooks", since = "1.10.0")]
@@ -323,9 +323,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl<'a, F: Future> Future for AssertUnwindSafe<F> {
     type Output = F::Output;
 
-    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
+    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
         let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
-        F::poll(pinned_field, lw)
+        F::poll(pinned_field, waker)
     }
 }
 
index bf689bad559d37f3936d2c55f691f3033e93498e..551e982a3c68566397967b4122bd60829c3bc17e 100644 (file)
 //! [`std::string`]: ../string/index.html
 //! [`std::vec`]: ../vec/index.html
 //! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
-//! [book-closures]: ../../book/first-edition/closures.html
-//! [book-dtor]: ../../book/first-edition/drop.html
-//! [book-enums]: ../../book/first-edition/enums.html
-//! [book-iter]: ../../book/first-edition/iterators.html
+//! [book-closures]: ../../book/ch13-01-closures.html
+//! [book-dtor]: ../../book/ch15-03-drop.html
+//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
+//! [book-iter]: ../../book/ch13-02-iterators.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 9b46c2180d9a25a3a05853b6872b85272ff03f6d..c03e3869aa3c87a09db7b761bd643ea926c0ffcf 100644 (file)
@@ -69,10 +69,6 @@ IMAGE_BASE:
     .asciz "Re-entered aborted enclave!"
 .Lreentry_panic_msg_end:
 
-.Lusercall_panic_msg:
-    .asciz "Invalid usercall#!"
-.Lusercall_panic_msg_end:
-
 .org .Lxsave_clear+512
 .Lxsave_header:
     .int 0, 0 /*  XSTATE_BV */
@@ -219,13 +215,21 @@ sgx_entry:
     orq $8,%rsp
     jmp panic_msg
 
-.Lusercall_panic:
-    lea .Lusercall_panic_msg(%rip),%rdi
-    mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
-    orq $8,%rsp
-    jmp panic_msg
-
-.macro push_callee_saved_registers
+/*  This *MUST* be called with 6 parameters, otherwise register information */
+/*  might leak! */
+.global usercall
+usercall:
+    test %rcx,%rcx            /* check `abort` function argument */
+    jnz .Lusercall_abort      /* abort is set, jump to abort code (unlikely forward conditional) */
+    jmp .Lusercall_save_state /* non-aborting usercall */
+.Lusercall_abort:
+/* set aborted bit */
+    movb $1,.Laborted(%rip)
+/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
+    testb $0xff,DEBUG(%rip)
+    jz .Lusercall_noreturn
+.Lusercall_save_state:
+/*  save callee-saved state */
     push %r15
     push %r14
     push %r13
@@ -235,33 +239,8 @@ sgx_entry:
     sub $8, %rsp
     fstcw 4(%rsp)
     stmxcsr (%rsp)
-.endm
-
-.global usercall_exit
-usercall_exit:
-/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
-    testb $0xff,DEBUG(%rip)
-    jz .Lskip_save_registers
-    push_callee_saved_registers
-    movq %rsp,%gs:tcsls_panic_last_rsp
-.Lskip_save_registers:
-/* set aborted bit */
-    movb $1,.Laborted(%rip)
-/* call usercall exit(true) */
-    /* NOP: mov %rsi,%rsi */ /*  RSI = usercall() argument: panic */
-    xor %rdx,%rdx /*  RDX cleared */
-    movq $usercall_nr_exit,%rdi /*  RDI = usercall exit */
-    jmp .Lexit
-
-/*  This *MUST* be called with 6 parameters, otherwise register information */
-/*  might leak! */
-.global usercall
-usercall:
-    test %rdi,%rdi
-    jle .Lusercall_panic
-/*  save callee-saved state */
-    push_callee_saved_registers
     movq %rsp,%gs:tcsls_last_rsp
+.Lusercall_noreturn:
 /*  clear general purpose register state */
     /*  RAX overwritten by ENCLU */
     /*  RBX set by sgx_exit */
@@ -281,7 +260,7 @@ usercall:
     jmp .Lsgx_exit
 .Lusercall_ret:
     movq $0,%gs:tcsls_last_rsp
-/*  restore callee-saved state, cf. push_callee_saved_registers */
+/*  restore callee-saved state, cf. "save" above */
     mov %r11,%rsp
     ldmxcsr (%rsp)
     fldcw 4(%rsp)
index 5ef069aa81c66641ca8904b9c70efb775a1ef067..509a1990d978b46ba7f533c649f958f268f99049 100644 (file)
@@ -12,7 +12,7 @@
 #[macro_use]
 pub mod usercalls;
 
-global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
+global_asm!(include_str!("entry.S"));
 
 #[no_mangle]
 unsafe extern "C" fn tcs_init(secondary: bool) {
index d23fa9a9ec6f9783c4c653101d8a22b1bc49f271..b2afacc70b82e504a5925675d12d1473eff03a57 100644 (file)
@@ -1,4 +1,4 @@
-use super::usercalls::alloc::UserRef;
+use super::usercalls::{alloc::UserRef, self};
 use cmp;
 use io::{self, Write};
 use mem;
@@ -52,7 +52,5 @@ fn flush(&mut self) -> io::Result<()> {
 #[no_mangle]
 pub extern "C" fn panic_msg(msg: &str) -> ! {
     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
-    unsafe { usercall_exit(true); }
+    usercalls::exit(true)
 }
-
-extern "C" { pub fn usercall_exit(panic: bool) -> !; }
index bae044b906b1621514f638d9252b0c83d8a42c3a..511d6e9e9273ab870cfbf9ca839438b49c9830a4 100644 (file)
@@ -120,7 +120,7 @@ pub unsafe fn launch_thread() -> IoResult<()> {
 /// Usercall `exit`. See the ABI documentation for more information.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn exit(panic: bool) -> ! {
-    unsafe { super::panic::usercall_exit(panic) }
+    unsafe { raw::exit(panic) }
 }
 
 /// Usercall `wait`. See the ABI documentation for more information.
index 004cf57602bc2118b7bb52dd963badc6e82881ce..447f20584f859ea6bde8abc77ffb9ffca41eb1f9 100644 (file)
@@ -4,12 +4,13 @@
 pub use fortanix_sgx_abi::*;
 
 use ptr::NonNull;
+use num::NonZeroU64;
 
 #[repr(C)]
 struct UsercallReturn(u64, u64);
 
 extern "C" {
-    fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
+    fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn;
 }
 
 /// Performs the raw usercall operation as defined in the ABI calling convention.
 ///
 /// Panics if `nr` is `0`.
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
-    if nr==0 { panic!("Invalid usercall number {}",nr) }
-    let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
+#[inline]
+pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool)
+    -> (u64, u64)
+{
+    let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4);
     (a, b)
 }
 
@@ -41,7 +44,6 @@ trait ReturnValue {
 }
 
 macro_rules! define_usercalls {
-    // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
         /// Usercall numbers as per the ABI.
         #[repr(u64)]
@@ -59,22 +61,6 @@ pub enum Usercalls {
     };
 }
 
-macro_rules! define_usercalls_asm {
-    ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
-        macro_rules! usercalls_asm {
-            () => {
-                concat!(
-                    ".equ usercall_nr_LAST, 0\n",
-                    $(
-                    ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
-                    ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
-                    ),*
-                )
-            }
-        }
-    };
-}
-
 macro_rules! define_ra {
     (< $i:ident > $t:ty) => {
         impl<$i> RegisterArgument for $t {
@@ -173,74 +159,90 @@ fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
     }
 }
 
+macro_rules! return_type_is_abort {
+    (!) => { true };
+    ($r:ty) => { false };
+}
+
+// In this macro: using `$r:tt` because `$r:ty` doesn't match ! in `return_type_is_abort`
 macro_rules! enclave_usercalls_internal_define_usercalls {
     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
-                     $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
+                     $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
                 RegisterArgument::into_register($n4),
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
-                0
+                0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
-                0,0
+                0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
-                0,0,0
+                0,0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident() -> $r:ty) => (
+    (def fn $f:ident() -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f() -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
-                0,0,0,0
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
+                0,0,0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
@@ -250,4 +252,3 @@ pub unsafe fn $f() -> $r {
 }
 
 invoke_with_usercalls!(define_usercalls);
-invoke_with_usercalls!(define_usercalls_asm);
index f2593c35bed14c6c79103d2716e6b0a098e9627f..4225ecbb206510d49f55c84a5dc1c876ccf0a928 100644 (file)
@@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
 }
 
 pub unsafe fn abort_internal() -> ! {
-    abi::panic::usercall_exit(true)
+    abi::usercalls::exit(true)
 }
 
 pub fn hashmap_random_keys() -> (u64, u64) {
index e753a74b925310e5870d4c94db5c66fb65ec9f99..5c7fb1b80446187007749a6e3ce55976def98eae 100644 (file)
@@ -6,7 +6,7 @@
 //! benchmarks themselves) should be done via the `#[test]` and
 //! `#[bench]` attributes.
 //!
-//! See the [Testing Chapter](../book/first-edition/testing.html) of the book for more details.
+//! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details.
 
 // Currently, not much of this is meant for users. It is intended to
 // support the simplest interface possible for representing and
index 7e446fdaeaf41740b32530035826090189f4d1de..b4f07ab33214cca85abd97673399deeaea057a9d 100644 (file)
@@ -4,7 +4,7 @@
 use std::iter::Iterator;
 use std::future::Future;
 
-use std::task::{Poll, LocalWaker};
+use std::task::{Poll, Waker};
 use std::pin::Pin;
 use std::unimplemented;
 
@@ -13,7 +13,7 @@
 impl Future for MyFuture {
    type Output = u32;
 
-   fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<u32> {
+   fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<u32> {
       Poll::Pending
    }
 }
diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs
new file mode 100644 (file)
index 0000000..1c700d4
--- /dev/null
@@ -0,0 +1,17 @@
+// revisions: rpass cfail
+
+trait Tr {
+    type Arr;
+
+    const C: usize = 0;
+}
+
+impl Tr for str {
+    #[cfg(rpass)]
+    type Arr = [u8; 8];
+    #[cfg(cfail)]
+    type Arr = [u8; Self::C];
+    //[cfail]~^ ERROR cycle detected when const-evaluating
+}
+
+fn main() {}
diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs
new file mode 100644 (file)
index 0000000..fe85baa
--- /dev/null
@@ -0,0 +1,66 @@
+// Test that we don't ICE when trying to dump MIR for unusual item types and
+// that we don't create filenames containing `<` and `>`
+
+struct A;
+
+impl A {
+    const ASSOCIATED_CONSTANT: i32 = 2;
+}
+
+enum E {
+    V = 5,
+}
+
+fn main() {
+    let v = Vec::<i32>::new();
+}
+
+// END RUST SOURCE
+
+// START rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
+// bb0: {
+//     _0 = const 2i32;
+//     return;
+// }
+// bb1: {
+//     resume;
+// }
+// END rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir
+
+// START rustc.E-V-{{constant}}.mir_map.0.mir
+// bb0: {
+//     _0 = const 5isize;
+//     return;
+// }
+// bb1: {
+//     resume;
+// }
+// END rustc.E-V-{{constant}}.mir_map.0.mir
+
+// START rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+//     bb0: {
+//     goto -> bb7;
+// }
+// bb1: {
+//     return;
+// }
+// bb2: {
+//     resume;
+// }
+// bb3: {
+//     goto -> bb1;
+// }
+// bb4: {
+//     goto -> bb2;
+// }
+// bb5: {
+//     drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> bb4;
+// }
+// bb6: {
+//     drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb3, unwind: bb4];
+// }
+// bb7: {
+//     _2 = &mut (*_1);
+//     _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5];
+// }
+// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
diff --git a/src/test/run-make/wasm-stringify-ints-small/Makefile b/src/test/run-make/wasm-stringify-ints-small/Makefile
new file mode 100644 (file)
index 0000000..26de6a0
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+       $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown
+       wc -c < $(TMPDIR)/foo.wasm
+       [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "20500" ]
+else
+all:
+endif
diff --git a/src/test/run-make/wasm-stringify-ints-small/foo.rs b/src/test/run-make/wasm-stringify-ints-small/foo.rs
new file mode 100644 (file)
index 0000000..7a947f0
--- /dev/null
@@ -0,0 +1,33 @@
+#![crate_type = "cdylib"]
+
+extern "C" {
+    fn observe(ptr: *const u8, len: usize);
+}
+
+macro_rules! s {
+    ( $( $f:ident -> $t:ty );* $(;)* ) => {
+        $(
+            extern "C" {
+                fn $f() -> $t;
+            }
+            let s = $f().to_string();
+            observe(s.as_ptr(), s.len());
+        )*
+    };
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn foo() {
+    s! {
+        get_u8 -> u8;
+        get_i8 -> i8;
+        get_u16 -> u16;
+        get_i16 -> i16;
+        get_u32 -> u32;
+        get_i32 -> i32;
+        get_u64 -> u64;
+        get_i64 -> i64;
+        get_usize -> usize;
+        get_isize -> isize;
+    }
+}
index 552f38215738bcbb4e5f8ed3b2078f27f90a0cf8..1843feed927a23ede730677397cdf7196c78b8a8 100644 (file)
@@ -1,7 +1,10 @@
 // edition:2018
+// aux-build:arc_wake.rs
 
 #![feature(arbitrary_self_types, async_await, await_macro, futures_api)]
 
+extern crate arc_wake;
+
 use std::pin::Pin;
 use std::future::Future;
 use std::sync::{
     atomic::{self, AtomicUsize},
 };
 use std::task::{
-    LocalWaker, Poll, Wake,
-    local_waker_from_nonlocal,
+    Poll, Waker,
 };
+use arc_wake::ArcWake;
 
 struct Counter {
     wakes: AtomicUsize,
 }
 
-impl Wake for Counter {
-    fn wake(this: &Arc<Self>) {
-        this.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+impl ArcWake for Counter {
+    fn wake(arc_self: &Arc<Self>) {
+        arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
     }
 }
 
@@ -29,11 +32,11 @@ fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
 
 impl Future for WakeOnceThenComplete {
     type Output = ();
-    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<()> {
+    fn poll(mut self: Pin<&mut Self>, waker: &Waker) -> Poll<()> {
         if self.0 {
             Poll::Ready(())
         } else {
-            lw.wake();
+            waker.wake();
             self.0 = true;
             Poll::Pending
         }
@@ -130,7 +133,7 @@ fn test_future_yields_once_then_returns<F, Fut>(f: F)
 {
     let mut fut = Box::pin(f(9));
     let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
-    let waker = local_waker_from_nonlocal(counter.clone());
+    let waker = ArcWake::into_waker(counter.clone());
     assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
     assert_eq!(Poll::Pending, fut.as_mut().poll(&waker));
     assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
diff --git a/src/test/run-pass/auxiliary/arc_wake.rs b/src/test/run-pass/auxiliary/arc_wake.rs
new file mode 100644 (file)
index 0000000..034e378
--- /dev/null
@@ -0,0 +1,56 @@
+// edition:2018
+
+#![feature(arbitrary_self_types, futures_api)]
+
+use std::sync::Arc;
+use std::task::{
+    Poll, Waker, RawWaker, RawWakerVTable,
+};
+
+macro_rules! waker_vtable {
+    ($ty:ident) => {
+        &RawWakerVTable {
+            clone: clone_arc_raw::<$ty>,
+            drop: drop_arc_raw::<$ty>,
+            wake: wake_arc_raw::<$ty>,
+        }
+    };
+}
+
+pub trait ArcWake {
+    fn wake(arc_self: &Arc<Self>);
+
+    fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
+    {
+        let ptr = Arc::into_raw(wake) as *const();
+
+        unsafe {
+            Waker::new_unchecked(RawWaker::new(ptr, waker_vtable!(Self)))
+        }
+    }
+}
+
+unsafe fn increase_refcount<T: ArcWake>(data: *const()) {
+    // Retain Arc by creating a copy
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    let arc_clone = arc.clone();
+    // Forget the Arcs again, so that the refcount isn't decrased
+    let _ = Arc::into_raw(arc);
+    let _ = Arc::into_raw(arc_clone);
+}
+
+unsafe fn clone_arc_raw<T: ArcWake>(data: *const()) -> RawWaker {
+    increase_refcount::<T>(data);
+    RawWaker::new(data, waker_vtable!(T))
+}
+
+unsafe fn drop_arc_raw<T: ArcWake>(data: *const()) {
+    // Drop Arc
+    let _: Arc<T> = Arc::from_raw(data as *const T);
+}
+
+unsafe fn wake_arc_raw<T: ArcWake>(data: *const()) {
+    let arc: Arc<T> = Arc::from_raw(data as *const T);
+    ArcWake::wake(&arc);
+    let _ = Arc::into_raw(arc);
+}
index e3023521100c4b141472471faad1675a9f739b80..fd4b585d3457273026d65391dcf3c03d3981ad36 100644 (file)
@@ -1,30 +1,28 @@
+// aux-build:arc_wake.rs
+
 #![feature(arbitrary_self_types, futures_api)]
 #![allow(unused)]
 
+extern crate arc_wake;
+
 use std::future::Future;
 use std::pin::Pin;
-use std::rc::Rc;
 use std::sync::{
     Arc,
     atomic::{self, AtomicUsize},
 };
 use std::task::{
-    Poll, Wake, Waker, LocalWaker,
-    local_waker, local_waker_from_nonlocal,
+    Poll, Waker,
 };
+use arc_wake::ArcWake;
 
 struct Counter {
-    local_wakes: AtomicUsize,
-    nonlocal_wakes: AtomicUsize,
+    wakes: AtomicUsize,
 }
 
-impl Wake for Counter {
-    fn wake(this: &Arc<Self>) {
-        this.nonlocal_wakes.fetch_add(1, atomic::Ordering::SeqCst);
-    }
-
-    unsafe fn wake_local(this: &Arc<Self>) {
-        this.local_wakes.fetch_add(1, atomic::Ordering::SeqCst);
+impl ArcWake for Counter {
+    fn wake(arc_self: &Arc<Self>) {
+        arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
     }
 }
 
@@ -32,40 +30,28 @@ unsafe fn wake_local(this: &Arc<Self>) {
 
 impl Future for MyFuture {
     type Output = ();
-    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
-        // Wake once locally
-        lw.wake();
-        // Wake twice non-locally
-        let waker = lw.clone().into_waker();
+    fn poll(self: Pin<&mut Self>, waker: &Waker) -> Poll<Self::Output> {
+        // Wake twice
         waker.wake();
         waker.wake();
         Poll::Ready(())
     }
 }
 
-fn test_local_waker() {
+fn test_waker() {
     let counter = Arc::new(Counter {
-        local_wakes: AtomicUsize::new(0),
-        nonlocal_wakes: AtomicUsize::new(0),
+        wakes: AtomicUsize::new(0),
     });
-    let waker = unsafe { local_waker(counter.clone()) };
-    assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&waker));
-    assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
-}
+    let waker = ArcWake::into_waker(counter.clone());
+    assert_eq!(2, Arc::strong_count(&counter));
 
-fn test_local_as_nonlocal_waker() {
-    let counter = Arc::new(Counter {
-        local_wakes: AtomicUsize::new(0),
-        nonlocal_wakes: AtomicUsize::new(0),
-    });
-    let waker: LocalWaker = local_waker_from_nonlocal(counter.clone());
     assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&waker));
-    assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst));
-    assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
+    assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst));
+
+    drop(waker);
+    assert_eq!(1, Arc::strong_count(&counter));
 }
 
 fn main() {
-    test_local_waker();
-    test_local_as_nonlocal_waker();
+    test_waker();
 }
diff --git a/src/test/rustdoc-js/substring.js b/src/test/rustdoc-js/substring.js
deleted file mode 100644 (file)
index 3a67501..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// exact-check
-
-const QUERY = 'waker_from';
-
-const EXPECTED = {
-    'others': [
-        { 'path': 'std::task', 'name': 'local_waker_from_nonlocal' },
-        { 'path': 'alloc::task', 'name': 'local_waker_from_nonlocal' },
-    ],
-};
index 383afe86cb405e40ee7f66bbefe274cb705ea488..c5248c52fb973313eefda0ff4143312fef01cbcd 100644 (file)
@@ -1,6 +1,8 @@
 #![feature(deprecated)]
 
+// @has deprecated_future/index.html '//*[@class="stab deprecated"]' \
+//      'Deprecated'
 // @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \
-//      'Deprecating in 99.99.99: effectively never'
+//      'Deprecated since 99.99.99: effectively never'
 #[deprecated(since = "99.99.99", note = "effectively never")]
 pub struct S;
diff --git a/src/test/rustdoc/rustc_deprecated-future.rs b/src/test/rustdoc/rustc_deprecated-future.rs
new file mode 100644 (file)
index 0000000..3133775
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(staged_api)]
+
+#![stable(feature = "rustc_deprecated-future-test", since = "1.0.0")]
+
+// @has rustc_deprecated_future/index.html '//*[@class="stab deprecated"]' \
+//      'Deprecation planned'
+// @has rustc_deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \
+//      'Deprecating in 99.99.99: effectively never'
+#[rustc_deprecated(since = "99.99.99", reason = "effectively never")]
+#[stable(feature = "rustc_deprecated-future-test", since = "1.0.0")]
+pub struct S;
index b9638722778ee3ecf9bfbb7b8e7f6d83ced8da98..d7ec41489d15615b186138b92abd3f6f46a83905 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `std::option`
   --> $DIR/bad-lint-cap2.rs:6:5
    |
 LL | use std::option; //~ ERROR
-   | ----^^^^^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/bad-lint-cap2.rs:4:9
index 21ed50b550afc7414503daae72ca61a1c5f6f3d4..5bf0b089afa20340b908341a8e8b4d00debec7e6 100644 (file)
@@ -2,7 +2,7 @@ warning: unused import: `std::option`
   --> $DIR/bad-lint-cap3.rs:7:5
    |
 LL | use std::option; //~ WARN
-   | ----^^^^^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/bad-lint-cap3.rs:4:9
index c6c60177e9d0ee2eec9178d67a08fce01c8ec8ce..138d902621cbcb2e3309181255b9030b66cbb204 100644 (file)
@@ -1,12 +1,14 @@
 // ignore-tidy-linelength
 
+// run-pass
+
 #![deny(deprecated_in_future)]
 
 #[deprecated(since = "99.99.99", note = "text")]
 pub fn deprecated_future() {}
 
 fn test() {
-    deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+    deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
 }
 
 fn main() {}
index 38392cf96084ce5e2fb2b0961438e2330fc9d0fa..81d2461c1bd83754232e1d426b3f29349d6ea451 100644 (file)
@@ -1,14 +1,8 @@
-error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
-  --> $DIR/deprecation-in-future.rs:9:5
+warning: use of deprecated item 'deprecated_future': text
+  --> $DIR/deprecation-in-future.rs:11:5
    |
-LL |     deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
+LL |     deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated
    |     ^^^^^^^^^^^^^^^^^
    |
-note: lint level defined here
-  --> $DIR/deprecation-in-future.rs:3:9
-   |
-LL | #![deny(deprecated_in_future)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
+   = note: #[warn(deprecated)] on by default
 
index 6b3e9a8ad8116dae8fb811c9150ce84183158d66..033d6eebbb21957542e11e245b2713001179d2a6 100644 (file)
@@ -261,8 +261,9 @@ fn test() {
         <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
         <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
 
-        deprecated_future(); // Fine; no error.
-        deprecated_future_text(); // Fine; no error.
+        // Future deprecations are only permitted for rustc_deprecated.
+        deprecated_future(); //~ ERROR use of deprecated item
+        deprecated_future_text(); //~ ERROR use of deprecated item
 
         let _ = DeprecatedStruct {
             //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text
index 46875d0bf13badbced57289d67141e0bd0f716ad..c48d06e86154d84b27b89d71927d4bc92a4b18d4 100644 (file)
@@ -214,128 +214,140 @@ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
 LL |         <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: use of deprecated item 'this_crate::deprecated_future': text
+  --> $DIR/deprecation-lint.rs:265:9
+   |
+LL |         deprecated_future(); //~ ERROR use of deprecated item
+   |         ^^^^^^^^^^^^^^^^^
+
+error: use of deprecated item 'this_crate::deprecated_future_text': text
+  --> $DIR/deprecation-lint.rs:266:9
+   |
+LL |         deprecated_future_text(); //~ ERROR use of deprecated item
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
 error: use of deprecated item 'this_crate::DeprecatedStruct': text
-  --> $DIR/deprecation-lint.rs:267:17
+  --> $DIR/deprecation-lint.rs:268:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
-  --> $DIR/deprecation-lint.rs:272:17
+  --> $DIR/deprecation-lint.rs:273:17
    |
 LL |         let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::DeprecatedUnitStruct': text
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
-  --> $DIR/deprecation-lint.rs:274:17
+  --> $DIR/deprecation-lint.rs:275:17
    |
 LL |         let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
-  --> $DIR/deprecation-lint.rs:276:17
+  --> $DIR/deprecation-lint.rs:277:17
    |
 LL |         let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::DeprecatedTupleStruct': text
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::nested::DeprecatedStruct': text
-  --> $DIR/deprecation-lint.rs:278:17
+  --> $DIR/deprecation-lint.rs:279:17
    |
 LL |         let _ = nested::DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
-  --> $DIR/deprecation-lint.rs:283:17
+  --> $DIR/deprecation-lint.rs:284:17
    |
 LL |         let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
-  --> $DIR/deprecation-lint.rs:285:17
+  --> $DIR/deprecation-lint.rs:286:17
    |
 LL |         let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
-  --> $DIR/deprecation-lint.rs:287:17
+  --> $DIR/deprecation-lint.rs:288:17
    |
 LL |         let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/deprecation-lint.rs:292:9
+  --> $DIR/deprecation-lint.rs:293:9
    |
 LL |         Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/deprecation-lint.rs:294:9
+  --> $DIR/deprecation-lint.rs:295:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/deprecation-lint.rs:296:9
+  --> $DIR/deprecation-lint.rs:297:9
    |
 LL |         Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/deprecation-lint.rs:298:9
+  --> $DIR/deprecation-lint.rs:299:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar'
-  --> $DIR/deprecation-lint.rs:316:13
+  --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar'
    |             ^^^
 
 error: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/deprecation-lint.rs:335:10
+  --> $DIR/deprecation-lint.rs:336:10
    |
 LL |     impl DeprecatedTrait for S { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
    |          ^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/deprecation-lint.rs:337:24
+  --> $DIR/deprecation-lint.rs:338:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text
    |                        ^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated': text
-  --> $DIR/deprecation-lint.rs:389:17
+  --> $DIR/deprecation-lint.rs:390:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated': text
-  --> $DIR/deprecation-lint.rs:398:13
+  --> $DIR/deprecation-lint.rs:399:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated': text
-  --> $DIR/deprecation-lint.rs:404:13
+  --> $DIR/deprecation-lint.rs:405:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2': text
-  --> $DIR/deprecation-lint.rs:409:17
+  --> $DIR/deprecation-lint.rs:410:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2': text
-  --> $DIR/deprecation-lint.rs:419:13
+  --> $DIR/deprecation-lint.rs:420:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2': text
-  --> $DIR/deprecation-lint.rs:428:13
+  --> $DIR/deprecation-lint.rs:429:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
@@ -593,136 +605,136 @@ LL |         <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated ite
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::DeprecatedStruct::i': text
-  --> $DIR/deprecation-lint.rs:269:13
+  --> $DIR/deprecation-lint.rs:270:13
    |
 LL |             i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text
    |             ^^^^
 
 error: use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
-  --> $DIR/deprecation-lint.rs:280:13
+  --> $DIR/deprecation-lint.rs:281:13
    |
 LL |             i: 0 //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text
    |             ^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/deprecation-lint.rs:291:13
+  --> $DIR/deprecation-lint.rs:292:13
    |
 LL |         foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/deprecation-lint.rs:293:9
+  --> $DIR/deprecation-lint.rs:294:9
    |
 LL |         <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/deprecation-lint.rs:295:13
+  --> $DIR/deprecation-lint.rs:296:13
    |
 LL |         foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/deprecation-lint.rs:297:9
+  --> $DIR/deprecation-lint.rs:298:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/deprecation-lint.rs:302:13
+  --> $DIR/deprecation-lint.rs:303:13
    |
 LL |         foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated'
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/deprecation-lint.rs:303:13
+  --> $DIR/deprecation-lint.rs:304:13
    |
 LL |         foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Stable::override2': text
-  --> $DIR/deprecation-lint.rs:362:13
+  --> $DIR/deprecation-lint.rs:363:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Stable::override2': text
-  --> $DIR/deprecation-lint.rs:366:17
+  --> $DIR/deprecation-lint.rs:367:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Stable::override2': text
-  --> $DIR/deprecation-lint.rs:370:13
+  --> $DIR/deprecation-lint.rs:371:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Stable2::2': text
-  --> $DIR/deprecation-lint.rs:378:17
+  --> $DIR/deprecation-lint.rs:379:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated item 'this_crate2::Stable2::2': text
-  --> $DIR/deprecation-lint.rs:383:20
+  --> $DIR/deprecation-lint.rs:384:20
    |
 LL |                    _)
    |                    ^
 
 error: use of deprecated item 'this_crate2::Deprecated::inherit': text
-  --> $DIR/deprecation-lint.rs:391:13
+  --> $DIR/deprecation-lint.rs:392:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated::inherit': text
-  --> $DIR/deprecation-lint.rs:395:17
+  --> $DIR/deprecation-lint.rs:396:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated::inherit': text
-  --> $DIR/deprecation-lint.rs:400:13
+  --> $DIR/deprecation-lint.rs:401:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2::0': text
-  --> $DIR/deprecation-lint.rs:412:17
+  --> $DIR/deprecation-lint.rs:413:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2::1': text
-  --> $DIR/deprecation-lint.rs:414:17
+  --> $DIR/deprecation-lint.rs:415:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2::2': text
-  --> $DIR/deprecation-lint.rs:416:17
+  --> $DIR/deprecation-lint.rs:417:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated item 'this_crate2::Deprecated2::0': text
-  --> $DIR/deprecation-lint.rs:421:14
+  --> $DIR/deprecation-lint.rs:422:14
    |
 LL |             (_,
    |              ^
 
 error: use of deprecated item 'this_crate2::Deprecated2::1': text
-  --> $DIR/deprecation-lint.rs:423:14
+  --> $DIR/deprecation-lint.rs:424:14
    |
 LL |              _,
    |              ^
 
 error: use of deprecated item 'this_crate2::Deprecated2::2': text
-  --> $DIR/deprecation-lint.rs:425:14
+  --> $DIR/deprecation-lint.rs:426:14
    |
 LL |              _)
    |              ^
 
-error: aborting due to 120 previous errors
+error: aborting due to 122 previous errors
 
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.rs b/src/test/ui/deprecation/rustc_deprecation-in-future.rs
new file mode 100644 (file)
index 0000000..a19363c
--- /dev/null
@@ -0,0 +1,15 @@
+// ignore-tidy-linelength
+
+#![deny(deprecated_in_future)]
+
+#![feature(staged_api)]
+
+#![stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
+
+#[rustc_deprecated(since = "99.99.99", reason = "effectively never")]
+#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")]
+pub struct S;
+
+fn main() {
+    let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+}
diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr
new file mode 100644 (file)
index 0000000..bd8ade1
--- /dev/null
@@ -0,0 +1,14 @@
+error: use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+  --> $DIR/rustc_deprecation-in-future.rs:14:13
+   |
+LL |     let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never
+   |             ^
+   |
+note: lint level defined here
+  --> $DIR/rustc_deprecation-in-future.rs:3:9
+   |
+LL | #![deny(deprecated_in_future)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 749c089ae9752dfc27f35e9fb77f257717eb34b4..819f5dd1cfc352ca57e52014f66cd79cc33d0b8e 100644 (file)
@@ -1,10 +1,11 @@
 fn main() {
-    if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types
-        //~^ expected (), found integer
-        //~| expected type `()`
-        //~| found type `{integer}`
+    if let Some(b) = None {
+        //~^ NOTE if let` arms have incompatible types
         ()
     } else {
         1
     };
+    //~^^ ERROR: `if let` arms have incompatible types
+    //~| NOTE expected (), found integer
+    //~| NOTE expected type `()`
 }
index fcf9e4695f675788a669ae9e0bacee521e9ac94b..6401a62c06ba26be8c4a85e72f014ee603c52a57 100644 (file)
@@ -1,25 +1,17 @@
 error[E0308]: `if let` arms have incompatible types
-  --> $DIR/if-let-arm-types.rs:2:5
+  --> $DIR/if-let-arm-types.rs:6:9
    |
-LL | /     if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types
-LL | |         //~^ expected (), found integer
-LL | |         //~| expected type `()`
-LL | |         //~| found type `{integer}`
-...  |
+LL | /     if let Some(b) = None {
+LL | |         //~^ NOTE if let` arms have incompatible types
+LL | |         ()
+LL | |     } else {
 LL | |         1
+   | |         ^ expected (), found integer
 LL | |     };
-   | |_____^ expected (), found integer
+   | |_____- `if let` arms have incompatible types
    |
    = note: expected type `()`
               found type `{integer}`
-note: `if let` arm with an incompatible type
-  --> $DIR/if-let-arm-types.rs:7:12
-   |
-LL |       } else {
-   |  ____________^
-LL | |         1
-LL | |     };
-   | |_____^
 
 error: aborting due to previous error
 
index fa82e974e1e29c91e481abd1b22e6504b2f2e6f8..b56e930158cc1be5ec073716719021c9421c7da8 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `super::f`
   --> $DIR/unused.rs:7:24
    |
 LL |         pub(super) use super::f; //~ ERROR unused
-   |         ---------------^^^^^^^^- help: remove the whole `use` item
+   |                        ^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/unused.rs:1:9
diff --git a/src/test/ui/issue-42944.rs b/src/test/ui/issue-42944.rs
new file mode 100644 (file)
index 0000000..9d74667
--- /dev/null
@@ -0,0 +1,19 @@
+mod foo {
+    pub struct B(());
+}
+
+mod bar {
+    use foo::B;
+
+    fn foo() {
+        B(()); //~ ERROR expected function, found struct `B` [E0423]
+    }
+}
+
+mod baz {
+    fn foo() {
+        B(()); //~ ERROR cannot find function `B` in this scope [E0425]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-42944.stderr b/src/test/ui/issue-42944.stderr
new file mode 100644 (file)
index 0000000..43fd0ff
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0423]: expected function, found struct `B`
+  --> $DIR/issue-42944.rs:9:9
+   |
+LL |         B(()); //~ ERROR expected function, found struct `B` [E0423]
+   |         ^ constructor is not visible here due to private fields
+
+error[E0425]: cannot find function `B` in this scope
+  --> $DIR/issue-42944.rs:15:9
+   |
+LL |         B(()); //~ ERROR cannot find function `B` in this scope [E0425]
+   |         ^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL |     use foo::B;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0425.
+For more information about an error, try `rustc --explain E0423`.
index ea901205544b621e7f998730fddf3edc0da0c215..726c437355e53cbef382f5706a69dd435def67a7 100644 (file)
@@ -1,12 +1,14 @@
 fn main() {
     match Some(10) {
-    //~^ ERROR match arms have incompatible types
-    //~| expected type `bool`
-    //~| found type `()`
-    //~| expected bool, found ()
+    //~^ NOTE `match` arms have incompatible types
         Some(5) => false,
+        //~^ NOTE this is found to be of type `bool`
         Some(2) => true,
+        //~^ NOTE this is found to be of type `bool`
         None    => (),
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected bool, found ()
+        //~| NOTE expected type `bool`
         _       => true
     }
 }
index 44d63ba3e687982ebb25d5e9050f55006a4707a9..10db477b8ca7bfd6fa9f3b2e13f6113f6ea3190e 100644 (file)
@@ -1,16 +1,20 @@
 error[E0308]: match arms have incompatible types
-  --> $DIR/issue-11319.rs:2:5
+  --> $DIR/issue-11319.rs:8:20
    |
 LL | /     match Some(10) {
-LL | |     //~^ ERROR match arms have incompatible types
-LL | |     //~| expected type `bool`
-LL | |     //~| found type `()`
-...  |
+LL | |     //~^ NOTE `match` arms have incompatible types
+LL | |         Some(5) => false,
+   | |                    ----- this is found to be of type `bool`
+LL | |         //~^ NOTE this is found to be of type `bool`
+LL | |         Some(2) => true,
+   | |                    ---- this is found to be of type `bool`
+LL | |         //~^ NOTE this is found to be of type `bool`
 LL | |         None    => (),
-   | |                    -- match arm with an incompatible type
+   | |                    ^^ expected bool, found ()
+...  |
 LL | |         _       => true
 LL | |     }
-   | |_____^ expected bool, found ()
+   | |_____- `match` arms have incompatible types
    |
    = note: expected type `bool`
               found type `()`
index 0f13ae3304d6cf3fd39e7e84e0e554b28b918ac4..15cea1d609d5382baed28eef39e9d99add1a8b00 100644 (file)
@@ -97,7 +97,7 @@ fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
 }
 
 fn str_to_direction(to_parse: &str) -> RoomDirection {
-    match to_parse { //~ ERROR match arms have incompatible types
+    match to_parse {
         "w" | "west" => RoomDirection::West,
         "e" | "east" => RoomDirection::East,
         "n" | "north" => RoomDirection::North,
@@ -108,6 +108,7 @@ fn str_to_direction(to_parse: &str) -> RoomDirection {
         "down" => RoomDirection::Down,
         _ => None
     }
+        //~^^ ERROR match arms have incompatible types
 }
 
 fn main() {
index 355868f05690fe20cbc00defdd04dcf1a58149bb..2c2efad19f5691ec076a5d63f2b4c9075436aef4 100644 (file)
@@ -10,17 +10,19 @@ LL |             Some(entry) => Ok(entry),
    |                            ^^^^^^^^^ ...but data from `room` is returned here
 
 error[E0308]: match arms have incompatible types
-  --> $DIR/issue-17728.rs:100:5
+  --> $DIR/issue-17728.rs:109:14
    |
-LL | /     match to_parse { //~ ERROR match arms have incompatible types
+LL | /     match to_parse {
 LL | |         "w" | "west" => RoomDirection::West,
 LL | |         "e" | "east" => RoomDirection::East,
 LL | |         "n" | "north" => RoomDirection::North,
 ...  |
+LL | |         "down" => RoomDirection::Down,
+   | |                   ------------------- this and all prior arms are found to be of type `RoomDirection`
 LL | |         _ => None
-   | |              ---- match arm with an incompatible type
+   | |              ^^^^ expected enum `RoomDirection`, found enum `std::option::Option`
 LL | |     }
-   | |_____^ expected enum `RoomDirection`, found enum `std::option::Option`
+   | |_____- `match` arms have incompatible types
    |
    = note: expected type `RoomDirection`
               found type `std::option::Option<_>`
index 3642085934abe860aa8a0da823ffbf07b9550392..2f501b941b5a6108a86de4329cbcae1460e1bd63 100644 (file)
@@ -6,11 +6,11 @@ fn closure_to_loc() {
 
 fn closure_from_match() {
     let x = match 1usize {
-    //~^ ERROR match arms have incompatible types
         1 => |c| c + 1,
         2 => |c| c - 1,
         _ => |c| c - 1
     };
+    //~^^^ ERROR match arms have incompatible types
 }
 
 fn main() { }
index 9f799c9b450692df8bd8a2c9544908a9f7ab168c..fa9935fcf619dadc969f5736b336cfde854ab7ec 100644 (file)
@@ -10,20 +10,20 @@ LL |     x = |c| c + 1;
    = help: consider boxing your closure and/or using it as a trait object
 
 error[E0308]: match arms have incompatible types
-  --> $DIR/issue-24036.rs:8:13
+  --> $DIR/issue-24036.rs:10:14
    |
 LL |       let x = match 1usize {
-   |  _____________^
-LL | |     //~^ ERROR match arms have incompatible types
+   |  _____________-
 LL | |         1 => |c| c + 1,
+   | |              --------- this is found to be of type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
 LL | |         2 => |c| c - 1,
-   | |              --------- match arm with an incompatible type
+   | |              ^^^^^^^^^ expected closure, found a different closure
 LL | |         _ => |c| c - 1
 LL | |     };
-   | |_____^ expected closure, found a different closure
+   | |_____- `match` arms have incompatible types
    |
-   = note: expected type `[closure@$DIR/issue-24036.rs:10:14: 10:23]`
-              found type `[closure@$DIR/issue-24036.rs:11:14: 11:23]`
+   = note: expected type `[closure@$DIR/issue-24036.rs:9:14: 9:23]`
+              found type `[closure@$DIR/issue-24036.rs:10:14: 10:23]`
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
 
index 3cfadd33b8fec2abde7f987f6054f7cdc565fa5a..0a901076f467aabf0b1e6627f364890e9d70db8e 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `std::thread`
   --> $DIR/issue-30730.rs:3:5
    |
 LL | use std::thread;
-   | ----^^^^^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/issue-30730.rs:2:9
index e588d24517c8cf02495cf99a3a807fbab337084f..170b98a12a848d275c311855be4273a1a93d0251 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `a::x`
   --> $DIR/lint-directives-on-use-items-issue-10534.rs:12:9
    |
 LL |     use a::x; //~ ERROR: unused import
-   |     ----^^^^- help: remove the whole `use` item
+   |         ^^^^
    |
 note: lint level defined here
   --> $DIR/lint-directives-on-use-items-issue-10534.rs:1:9
@@ -14,7 +14,7 @@ error: unused import: `a::y`
   --> $DIR/lint-directives-on-use-items-issue-10534.rs:21:9
    |
 LL |     use a::y; //~ ERROR: unused import
-   |     ----^^^^- help: remove the whole `use` item
+   |         ^^^^
    |
 note: lint level defined here
   --> $DIR/lint-directives-on-use-items-issue-10534.rs:20:12
index 7970b0201db70bd20a605cb4e8ce0f630d1a8da9..18f2fae0067eb94cdd9c313f1ab6641ec1e62433 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `std::fmt::{}`
   --> $DIR/lint-unused-imports.rs:8:5
    |
 LL | use std::fmt::{};
-   | ----^^^^^^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/lint-unused-imports.rs:1:9
@@ -14,39 +14,37 @@ error: unused imports: `None`, `Some`
   --> $DIR/lint-unused-imports.rs:12:27
    |
 LL | use std::option::Option::{Some, None};
-   | --------------------------^^^^--^^^^-- help: remove the whole `use` item
+   |                           ^^^^  ^^^^
 
 error: unused import: `test::A`
   --> $DIR/lint-unused-imports.rs:15:5
    |
 LL | use test::A;       //~ ERROR unused import: `test::A`
-   | ----^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^
 
 error: unused import: `bar`
   --> $DIR/lint-unused-imports.rs:24:18
    |
 LL | use test2::{foo, bar}; //~ ERROR unused import: `bar`
-   |                --^^^
-   |                |
-   |                help: remove the unused import
+   |                  ^^^
 
 error: unused import: `foo::Square`
   --> $DIR/lint-unused-imports.rs:52:13
    |
 LL |         use foo::Square; //~ ERROR unused import: `foo::Square`
-   |         ----^^^^^^^^^^^- help: remove the whole `use` item
+   |             ^^^^^^^^^^^
 
 error: unused import: `self::g`
   --> $DIR/lint-unused-imports.rs:68:9
    |
 LL |     use self::g; //~ ERROR unused import: `self::g`
-   |     ----^^^^^^^- help: remove the whole `use` item
+   |         ^^^^^^^
 
 error: unused import: `test2::foo`
   --> $DIR/lint-unused-imports.rs:77:9
    |
 LL |     use test2::foo; //~ ERROR unused import: `test2::foo`
-   |     ----^^^^^^^^^^- help: remove the whole `use` item
+   |         ^^^^^^^^^^
 
 error: unused import: `test::B2`
   --> $DIR/lint-unused-imports.rs:20:5
index b808ca708a31195e94c5e9f70221ccf637e8315b..8287ca5692bd98f3485f4d451bcc1166fd0954c0 100644 (file)
@@ -2,7 +2,7 @@ warning: unused import: `std::string::ToString`
   --> $DIR/lints-in-foreign-macros.rs:11:16
    |
 LL |     () => {use std::string::ToString;} //~ WARN: unused import
-   |            ----^^^^^^^^^^^^^^^^^^^^^- help: remove the whole `use` item
+   |                ^^^^^^^^^^^^^^^^^^^^^
 ...
 LL | mod a { foo!(); }
    |         ------- in this macro invocation
@@ -17,13 +17,13 @@ warning: unused import: `std::string::ToString`
   --> $DIR/lints-in-foreign-macros.rs:16:18
    |
 LL | mod c { baz!(use std::string::ToString;); } //~ WARN: unused import
-   |              ----^^^^^^^^^^^^^^^^^^^^^- help: remove the whole `use` item
+   |                  ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused import: `std::string::ToString`
   --> $DIR/lints-in-foreign-macros.rs:17:19
    |
 LL | mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import
-   |               ----^^^^^^^^^^^^^^^^^^^^^- help: remove the whole `use` item
+   |                   ^^^^^^^^^^^^^^^^^^^^^
 
 warning: missing documentation for crate
   --> $DIR/lints-in-foreign-macros.rs:4:1
diff --git a/src/test/ui/match/match-type-err-first-arm.rs b/src/test/ui/match/match-type-err-first-arm.rs
new file mode 100644 (file)
index 0000000..b4b84ef
--- /dev/null
@@ -0,0 +1,45 @@
+fn main() {
+    let _ = test_func1(1);
+    let _ = test_func2(1);
+}
+
+fn test_func1(n: i32) -> i32 {
+    //~^ NOTE expected `i32` because of return type
+    match n {
+        12 => 'b',
+        //~^ ERROR mismatched types
+        //~| NOTE expected i32, found char
+        _ => 42,
+    }
+}
+
+fn test_func2(n: i32) -> i32 {
+    let x = match n {
+    //~^ NOTE `match` arms have incompatible types
+        12 => 'b',
+        //~^ NOTE this is found to be of type `char`
+        _ => 42,
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected char, found integer
+        //~| NOTE expected type `char`
+    };
+    x
+}
+
+fn test_func3(n: i32) -> i32 {
+    let x = match n {
+    //~^ NOTE `match` arms have incompatible types
+        1 => 'b',
+        2 => 'b',
+        3 => 'b',
+        4 => 'b',
+        5 => 'b',
+        6 => 'b',
+        //~^ NOTE this and all prior arms are found to be of type `char`
+        _ => 42,
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected char, found integer
+        //~| NOTE expected type `char`
+    };
+    x
+}
diff --git a/src/test/ui/match/match-type-err-first-arm.stderr b/src/test/ui/match/match-type-err-first-arm.stderr
new file mode 100644 (file)
index 0000000..db8bef8
--- /dev/null
@@ -0,0 +1,53 @@
+error[E0308]: mismatched types
+  --> $DIR/match-type-err-first-arm.rs:9:15
+   |
+LL | fn test_func1(n: i32) -> i32 {
+   |                          --- expected `i32` because of return type
+...
+LL |         12 => 'b',
+   |               ^^^ expected i32, found char
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/match-type-err-first-arm.rs:21:14
+   |
+LL |       let x = match n {
+   |  _____________-
+LL | |     //~^ NOTE `match` arms have incompatible types
+LL | |         12 => 'b',
+   | |               --- this is found to be of type `char`
+LL | |         //~^ NOTE this is found to be of type `char`
+LL | |         _ => 42,
+   | |              ^^ expected char, found integer
+...  |
+LL | |         //~| NOTE expected type `char`
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `char`
+              found type `{integer}`
+
+error[E0308]: match arms have incompatible types
+  --> $DIR/match-type-err-first-arm.rs:39:14
+   |
+LL |       let x = match n {
+   |  _____________-
+LL | |     //~^ NOTE `match` arms have incompatible types
+LL | |         1 => 'b',
+LL | |         2 => 'b',
+...  |
+LL | |         6 => 'b',
+   | |              --- this and all prior arms are found to be of type `char`
+LL | |         //~^ NOTE this and all prior arms are found to be of type `char`
+LL | |         _ => 42,
+   | |              ^^ expected char, found integer
+...  |
+LL | |         //~| NOTE expected type `char`
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `char`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 86841706325f7e6da352084eb9810986a573beac..469c22fdb17d7b6aedbf12e8cfa4500d57b41674 100644 (file)
@@ -6,7 +6,7 @@
 #![stable(feature = "stable_test_feature", since = "1.0.0")]
 
 pub fn unmarked() {
-    //~^ ERROR This node does not have a stability attribute
+    //~^ ERROR function has missing stability attribute
     ()
 }
 
@@ -20,5 +20,5 @@ pub fn unmarked() {}
 pub mod bar {
     // #[stable] is not inherited
     pub fn unmarked() {}
-    //~^ ERROR This node does not have a stability attribute
+    //~^ ERROR function has missing stability attribute
 }
index e55bd00e2c6731c03159b5e0c5953e877dfd6ef7..6c81f2bac57889753083ab52d233ae573380ca80 100644 (file)
@@ -1,13 +1,13 @@
-error: This node does not have a stability attribute
+error: function has missing stability attribute
   --> $DIR/missing-stability.rs:8:1
    |
 LL | / pub fn unmarked() {
-LL | |     //~^ ERROR This node does not have a stability attribute
+LL | |     //~^ ERROR function has missing stability attribute
 LL | |     ()
 LL | | }
    | |_^
 
-error: This node does not have a stability attribute
+error: function has missing stability attribute
   --> $DIR/missing-stability.rs:22:5
    |
 LL |     pub fn unmarked() {}
index 44ecf6b97bf509da5d85383989607aae62a2ce28..519e74d9f631583dd55586e43a830183ac254168 100644 (file)
@@ -2,25 +2,16 @@ error[E0423]: expected value, found struct `Z`
   --> $DIR/privacy-struct-ctor.rs:20:9
    |
 LL |         Z;
-   |         ^ constructor is not visible here due to private fields
-help: a tuple struct with a similar name exists
-   |
-LL |         S;
    |         ^
-help: possible better candidate is found in another module, you can import it into scope
-   |
-LL |     use m::n::Z;
-   |
+   |         |
+   |         constructor is not visible here due to private fields
+   |         help: a tuple struct with a similar name exists: `S`
 
 error[E0423]: expected value, found struct `S`
   --> $DIR/privacy-struct-ctor.rs:33:5
    |
 LL |     S;
    |     ^ constructor is not visible here due to private fields
-help: possible better candidate is found in another module, you can import it into scope
-   |
-LL | use m::S;
-   |
 
 error[E0423]: expected value, found struct `S2`
   --> $DIR/privacy-struct-ctor.rs:38:5
index c7b36eaf2e76b4f10e9e53727ce9c5633839fc12..308035919260377fcf1e64ae1aded3dfbb9f4ec6 100644 (file)
@@ -2,7 +2,7 @@ warning: unused import: `m::Tr1 as _`
   --> $DIR/basic.rs:26:9
    |
 LL |     use m::Tr1 as _; //~ WARN unused import
-   |     ----^^^^^^^^^^^- help: remove the whole `use` item
+   |         ^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/basic.rs:4:9
@@ -14,5 +14,5 @@ warning: unused import: `S as _`
   --> $DIR/basic.rs:27:9
    |
 LL |     use S as _; //~ WARN unused import
-   |     ----^^^^^^- help: remove the whole `use` item
+   |         ^^^^^^
 
index 0bbc17276d98ba899a86eb0e8e09bf6ef635a8ac..4163c2876074befdc95f7a8fda5184b84e03d9a2 100644 (file)
@@ -2,7 +2,7 @@ error: unused import: `core::any`
   --> $DIR/unused-2018.rs:6:9
    |
 LL |     use core::any; //~ ERROR unused import: `core::any`
-   |     ----^^^^^^^^^- help: remove the whole `use` item
+   |         ^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/unused-2018.rs:3:9
@@ -14,7 +14,7 @@ error: unused import: `core`
   --> $DIR/unused-2018.rs:10:9
    |
 LL |     use core; //~ ERROR unused import: `core`
-   |     ----^^^^- help: remove the whole `use` item
+   |         ^^^^
 
 error: aborting due to 2 previous errors
 
index 6bd0e9be81f5ec047f1d3dd42ac05947f5fa5102..a730d081b7c035e0e2330fc5fce8029f09033665 100644 (file)
@@ -10,8 +10,4 @@ note: lint level defined here
 LL | #![warn(unused)]
    |         ^^^^^^
    = note: #[warn(unused_imports)] implied by #[warn(unused)]
-help: remove the unused imports
-   |
-LL | use std::cmp::{min};
-   |               -- --
 
diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs
new file mode 100644 (file)
index 0000000..8f750ae
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(staged_api)]
+//~^ ERROR crate has missing stability attribute
+
+fn main() {}
diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr
new file mode 100644 (file)
index 0000000..f674797
--- /dev/null
@@ -0,0 +1,11 @@
+error: crate has missing stability attribute
+  --> $DIR/missing-stability-attr-at-top-level.rs:1:1
+   |
+LL | / #![feature(staged_api)]
+LL | | //~^ ERROR crate has missing stability attribute
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to previous error
+
index 596a6eb6ed366f174849c5df5d7493272bdbe147..0b243bb52119bae080f3163343f3b4e6ff61340e 100644 (file)
@@ -2,7 +2,7 @@
 #![stable(feature = "test", since = "0")]
 
 #[stable(feature = "test", since = "0")]
-pub struct Reverse<T>(pub T); //~ ERROR This node does not have a stability attribute
+pub struct Reverse<T>(pub T); //~ ERROR field has missing stability attribute
 
 fn main() {
     // Make sure the field is used to fill the stability cache
index e123f420233249f7f1382a723052382582e52615..7ffb4bb487a7b514b3cc04a50156efe38ee05739 100644 (file)
@@ -1,7 +1,7 @@
-error: This node does not have a stability attribute
+error: field has missing stability attribute
   --> $DIR/stability-attribute-issue-43027.rs:5:23
    |
-LL | pub struct Reverse<T>(pub T); //~ ERROR This node does not have a stability attribute
+LL | pub struct Reverse<T>(pub T); //~ ERROR field has missing stability attribute
    |                       ^^^^^
 
 error: aborting due to previous error
index 0c132e8857550e9f0d60867f3ca9797c3d4eeb17..13ef3d3f53d2b0dc2629249eda300d8c6f90ed38 100644 (file)
@@ -5,7 +5,7 @@
 #![stable(feature = "stable_test_feature", since = "1.0.0")]
 
 #[macro_export]
-macro_rules! mac { //~ ERROR This node does not have a stability attribute
+macro_rules! mac { //~ ERROR macro has missing stability attribute
     () => ()
 }
 
index d42dcc0c778a7fb53ee3d732c8d29d3540527114..1c759d49b9947483a4c22529d566f7466782de29 100644 (file)
@@ -1,7 +1,7 @@
-error: This node does not have a stability attribute
+error: macro has missing stability attribute
   --> $DIR/stability-attribute-sanity-3.rs:8:1
    |
-LL | / macro_rules! mac { //~ ERROR This node does not have a stability attribute
+LL | / macro_rules! mac { //~ ERROR macro has missing stability attribute
 LL | |     () => ()
 LL | | }
    | |_^
index 7273496a7ce06ba820cd09685b19829d3d4c4c5e..8143acc957b4ca243a802a432355645c413dd6e0 100644 (file)
@@ -2,9 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/as-ref.rs:6:27
    |
 LL |   opt.map(|arg| takes_ref(arg));
-   |       -                   ^^^ expected &Foo, found struct `Foo`
+   |       ---                 ^^^ expected &Foo, found struct `Foo`
    |       |
-   |       help: consider using `as_ref` instead: `as_ref().`
+   |       help: consider using `as_ref` instead: `as_ref().map`
    |
    = note: expected type `&Foo`
               found type `Foo`
@@ -13,9 +13,9 @@ error[E0308]: mismatched types
   --> $DIR/as-ref.rs:8:37
    |
 LL |   opt.and_then(|arg| Some(takes_ref(arg)));
-   |       -                             ^^^ expected &Foo, found struct `Foo`
+   |       --------                      ^^^ expected &Foo, found struct `Foo`
    |       |
-   |       help: consider using `as_ref` instead: `as_ref().`
+   |       help: consider using `as_ref` instead: `as_ref().and_then`
    |
    = note: expected type `&Foo`
               found type `Foo`
@@ -24,9 +24,9 @@ error[E0308]: mismatched types
   --> $DIR/as-ref.rs:11:27
    |
 LL |   opt.map(|arg| takes_ref(arg));
-   |       -                   ^^^ expected &Foo, found struct `Foo`
+   |       ---                 ^^^ expected &Foo, found struct `Foo`
    |       |
-   |       help: consider using `as_ref` instead: `as_ref().`
+   |       help: consider using `as_ref` instead: `as_ref().map`
    |
    = note: expected type `&Foo`
               found type `Foo`
@@ -35,9 +35,9 @@ error[E0308]: mismatched types
   --> $DIR/as-ref.rs:13:35
    |
 LL |   opt.and_then(|arg| Ok(takes_ref(arg)));
-   |       -                           ^^^ expected &Foo, found struct `Foo`
+   |       --------                    ^^^ expected &Foo, found struct `Foo`
    |       |
-   |       help: consider using `as_ref` instead: `as_ref().`
+   |       help: consider using `as_ref` instead: `as_ref().and_then`
    |
    = note: expected type `&Foo`
               found type `Foo`
index 6af6f449de5e6b5d2f14390409f37a4336dabf38..c8df6cbc57dcab71de0cb3fdeb8a58dbeb07afbb 100644 (file)
@@ -2,7 +2,7 @@ error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
   --> $DIR/use-nested-groups-unused-imports.rs:16:11
    |
 LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};
-   | ----------^^^--------^^^^^^^--^^^^^^^^^---^-- help: remove the whole `use` item
+   |           ^^^        ^^^^^^^  ^^^^^^^^^   ^
    |
 note: lint level defined here
   --> $DIR/use-nested-groups-unused-imports.rs:3:9
@@ -14,15 +14,13 @@ error: unused import: `*`
   --> $DIR/use-nested-groups-unused-imports.rs:18:24
    |
 LL | use foo::bar::baz::{*, *};
-   |                      --^
-   |                      |
-   |                      help: remove the unused import
+   |                        ^
 
 error: unused import: `foo::{}`
   --> $DIR/use-nested-groups-unused-imports.rs:20:5
    |
 LL | use foo::{};
-   | ----^^^^^^^- help: remove the whole `use` item
+   |     ^^^^^^^
 
 error: aborting due to 3 previous errors
 
index 323f81181682f45a9bb41bf36bf92d3ca7daec9f..ed697fc5425352b5b9d01eca284219ce010bdf3c 100755 (executable)
@@ -24,6 +24,17 @@ MAINTAINERS = {
     'rust-by-example': '@steveklabnik @marioidival @projektir',
 }
 
+REPOS = {
+    'miri': 'https://github.com/solson/miri',
+    'clippy-driver': 'https://github.com/rust-lang/rust-clippy',
+    'rls': 'https://github.com/rust-lang/rls',
+    'rustfmt': 'https://github.com/rust-lang/rustfmt',
+    'book': 'https://github.com/rust-lang/book',
+    'nomicon': 'https://github.com/rust-lang-nursery/nomicon',
+    'reference': 'https://github.com/rust-lang-nursery/reference',
+    'rust-by-example': 'https://github.com/rust-lang/rust-by-example',
+}
+
 
 def read_current_status(current_commit, path):
     '''Reads build status of `current_commit` from content of `history/*.tsv`
@@ -35,11 +46,48 @@ def read_current_status(current_commit, path):
                 return json.loads(status)
     return {}
 
+def issue(
+    tool,
+    maintainers,
+    relevant_pr_number,
+    relevant_pr_user,
+    pr_reviewer,
+):
+    # Open an issue about the toolstate failure.
+    gh_url = 'https://api.github.com/repos/rust-lang/rust/issues'
+    assignees = [x.strip() for x in maintainers.split('@') if x != '']
+    assignees.append(relevant_pr_user)
+    response = urllib2.urlopen(urllib2.Request(
+        gh_url,
+        json.dumps({
+            'body': textwrap.dedent('''\
+            Hello, this is your friendly neighborhood mergebot.
+            After merging PR {}, I observed that the tool {} no longer builds.
+            A follow-up PR to the repository {} is needed to fix the fallout.
+
+            cc @{}, do you think you would have time to do the follow-up work?
+            If so, that would be great!
+
+            cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
+
+            ''').format(relevant_pr_number, tool, REPOS[tool], relevant_pr_user, pr_reviewer),
+            'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
+            'assignees': assignees,
+            'labels': ['T-compiler', 'I-nominated'],
+        }),
+        {
+            'Authorization': 'token ' + github_token,
+            'Content-Type': 'application/json',
+        }
+    ))
+    response.read()
 
 def update_latest(
     current_commit,
     relevant_pr_number,
     relevant_pr_url,
+    relevant_pr_user,
+    pr_reviewer,
     current_datetime
 ):
     '''Updates `_data/latest.json` to match build result of the given commit.
@@ -64,19 +112,41 @@ def update_latest(
         for status in latest:
             tool = status['tool']
             changed = False
+            build_failed = False
 
             for os, s in current_status.items():
                 old = status[os]
                 new = s.get(tool, old)
                 status[os] = new
                 if new > old:
+                    # things got fixed or at least the status quo improved
                     changed = True
                     message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
                         .format(tool, os, old, new, MAINTAINERS.get(tool))
                 elif new < old:
+                    # tests or builds are failing and were not failing before
                     changed = True
-                    message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
-                        .format(tool, os, old, new, MAINTAINERS.get(tool))
+                    title = '💔 {} on {}: {} → {}' \
+                        .format(tool, os, old, new)
+                    message += '{} (cc {}, @rust-lang/infra).\n' \
+                        .format(title, MAINTAINERS.get(tool))
+                    # only create issues for build failures. Other failures can be spurious
+                    if new == 'build-fail':
+                        build_failed = True
+
+            if build_failed:
+                try:
+                    issue(
+                        tool, MAINTAINERS.get(tool),
+                        relevant_pr_number, relevant_pr_user, pr_reviewer,
+                    )
+                except IOError as (errno, strerror):
+                    # network errors will simply end up not creating an issue, but that's better
+                    # than failing the entire build job
+                    print "I/O error({0}): {1}".format(errno, strerror)
+                except:
+                    print "Unexpected error:", sys.exc_info()[0]
+                    raise
 
             if changed:
                 status['commit'] = current_commit
@@ -99,20 +169,30 @@ if __name__ == '__main__':
     save_message_to_path = sys.argv[3]
     github_token = sys.argv[4]
 
-    relevant_pr_match = re.search('#([0-9]+)', cur_commit_msg)
+    # assume that PR authors are also owners of the repo where the branch lives
+    relevant_pr_match = re.search(
+        'Auto merge of #([0-9]+) - ([^:]+):[^,]+ r=([^\s]+)',
+        cur_commit_msg,
+    )
     if relevant_pr_match:
         number = relevant_pr_match.group(1)
+        relevant_pr_user = relevant_pr_match.group(2)
         relevant_pr_number = 'rust-lang/rust#' + number
         relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number
+        pr_reviewer = relevant_pr_match.group(3)
     else:
         number = '-1'
+        relevant_pr_user = '<unknown user>'
         relevant_pr_number = '<unknown PR>'
         relevant_pr_url = '<unknown>'
+        pr_reviewer = '<unknown reviewer>'
 
     message = update_latest(
         cur_commit,
         relevant_pr_number,
         relevant_pr_url,
+        relevant_pr_user,
+        pr_reviewer,
         cur_datetime
     )
     if not message: