about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/sync.rs73
-rw-r--r--src/liballoc/task.rs12
-rw-r--r--src/libcore/ops/drop.rs142
-rw-r--r--src/librustc_parse/parser/expr.rs54
-rw-r--r--src/librustc_parse/parser/item.rs2
-rw-r--r--src/librustc_parse/parser/stmt.rs2
-rw-r--r--src/librustc_resolve/diagnostics.rs19
-rw-r--r--src/librustc_resolve/late/diagnostics.rs11
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs20
-rw-r--r--src/test/ui/associated-types/associated-types-overridden-binding.stderr12
-rw-r--r--src/test/ui/async-await/edition-deny-async-fns-2015.stderr27
-rw-r--r--src/test/ui/class-missing-self.stderr2
-rw-r--r--src/test/ui/crate-in-paths.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr2
-rw-r--r--src/test/ui/editions/async-block-2015.rs30
-rw-r--r--src/test/ui/editions/async-block-2015.stderr41
-rw-r--r--src/test/ui/glob-resolve1.stderr12
-rw-r--r--src/test/ui/hygiene/globs.stderr8
-rw-r--r--src/test/ui/impl-trait/universal_wrong_bounds.stderr4
-rw-r--r--src/test/ui/issues/issue-12028.stderr6
-rw-r--r--src/test/ui/issues/issue-17546.stderr4
-rw-r--r--src/test/ui/issues/issue-35675.stderr4
-rw-r--r--src/test/ui/issues/issue-37534.stderr2
-rw-r--r--src/test/ui/issues/issue-38293.stderr2
-rw-r--r--src/test/ui/issues/issue-42944.stderr2
-rw-r--r--src/test/ui/issues/issue-4366-2.stderr4
-rw-r--r--src/test/ui/issues/issue-4366.stderr2
-rw-r--r--src/test/ui/issues/issue-50599.stderr2
-rw-r--r--src/test/ui/issues/issue-69455.rs2
-rw-r--r--src/test/ui/issues/issue-69455.stderr12
-rw-r--r--src/test/ui/issues/issue-69683.rs32
-rw-r--r--src/test/ui/issues/issue-69683.stderr9
-rw-r--r--src/test/ui/issues/issue-71584.rs5
-rw-r--r--src/test/ui/issues/issue-71584.stderr9
-rw-r--r--src/test/ui/lexical-scopes.stderr2
-rw-r--r--src/test/ui/lint/use_suggestion_json.stderr4
-rw-r--r--src/test/ui/macros/macro-outer-attributes.stderr2
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr8
-rw-r--r--src/test/ui/no-implicit-prelude-nested.stderr30
-rw-r--r--src/test/ui/no-implicit-prelude.stderr10
-rw-r--r--src/test/ui/parser/circular_modules_main.stderr2
-rw-r--r--src/test/ui/privacy/privacy-ns1.stderr6
-rw-r--r--src/test/ui/privacy/privacy-ns2.stderr6
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules-fail.stderr4
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr8
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.stderr2
-rw-r--r--src/test/ui/resolve/enums-are-namespaced-xc.stderr6
-rw-r--r--src/test/ui/resolve/issue-16058.stderr2
-rw-r--r--src/test/ui/resolve/issue-17518.stderr2
-rw-r--r--src/test/ui/resolve/issue-21221-1.stderr6
-rw-r--r--src/test/ui/resolve/issue-21221-2.stderr2
-rw-r--r--src/test/ui/resolve/issue-21221-3.stderr2
-rw-r--r--src/test/ui/resolve/issue-21221-4.stderr2
-rw-r--r--src/test/ui/resolve/issue-3907.stderr2
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr12
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr2
-rw-r--r--src/test/ui/resolve/resolve-primitive-fallback.stderr2
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.stderr6
-rw-r--r--src/test/ui/rust-2018/issue-52202-use-suggestions.stderr2
-rw-r--r--src/test/ui/self/self_type_keyword.stderr2
-rw-r--r--src/test/ui/span/issue-35987.stderr2
-rw-r--r--src/test/ui/suggestions/no-extern-crate-in-type.stderr2
-rw-r--r--src/test/ui/suggestions/raw-name-use-suggestion.stderr2
-rw-r--r--src/test/ui/use/use-super-global-path.stderr2
64 files changed, 492 insertions, 222 deletions
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index a81e0cf7e1d..19d289c87fd 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -776,6 +776,79 @@ impl<T: ?Sized> Arc<T> {
         this.inner().strong.load(SeqCst)
     }
 
+    /// Increments the strong reference count on the `Arc<T>` associated with the
+    /// provided pointer by one.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must have been obtained through `Arc::into_raw`, and the
+    /// associated `Arc` instance must be valid (i.e. the strong count must be at
+    /// least 1) for the duration of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(arc_mutate_strong_count)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let five = Arc::new(5);
+    ///
+    /// unsafe {
+    ///     let ptr = Arc::into_raw(five);
+    ///     Arc::incr_strong_count(ptr);
+    ///
+    ///     // This assertion is deterministic because we haven't shared
+    ///     // the `Arc` between threads.
+    ///     let five = Arc::from_raw(ptr);
+    ///     assert_eq!(2, Arc::strong_count(&five));
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
+    pub unsafe fn incr_strong_count(ptr: *const T) {
+        // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop
+        let arc = mem::ManuallyDrop::new(Arc::<T>::from_raw(ptr));
+        // Now increase refcount, but don't drop new refcount either
+        let _arc_clone: mem::ManuallyDrop<_> = arc.clone();
+    }
+
+    /// Decrements the strong reference count on the `Arc<T>` associated with the
+    /// provided pointer by one.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must have been obtained through `Arc::into_raw`, and the
+    /// associated `Arc` instance must be valid (i.e. the strong count must be at
+    /// least 1) when invoking this method. This method can be used to release the final
+    /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
+    /// released.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(arc_mutate_strong_count)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let five = Arc::new(5);
+    ///
+    /// unsafe {
+    ///     let ptr = Arc::into_raw(five);
+    ///     Arc::decr_strong_count(ptr);
+    ///
+    ///     // This assertion is deterministic because we haven't shared
+    ///     // the `Arc` between threads.
+    ///     let five = Arc::from_raw(ptr);
+    ///     assert_eq!(0, Arc::strong_count(&five));
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "arc_mutate_strong_count", issue = "71983")]
+    pub unsafe fn decr_strong_count(ptr: *const T) {
+        mem::drop(Arc::from_raw(ptr));
+    }
+
     #[inline]
     fn inner(&self) -> &ArcInner<T> {
         // This unsafety is ok because while this arc is alive we're guaranteed
diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs
index a64d5d7a63b..745444a152e 100644
--- a/src/liballoc/task.rs
+++ b/src/liballoc/task.rs
@@ -1,6 +1,6 @@
 #![unstable(feature = "wake_trait", issue = "69912")]
 //! Types and Traits for working with asynchronous tasks.
-use core::mem::{self, ManuallyDrop};
+use core::mem::ManuallyDrop;
 use core::task::{RawWaker, RawWakerVTable, Waker};
 
 use crate::sync::Arc;
@@ -60,9 +60,11 @@ impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker {
 fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
     // Increment the reference count of the arc to clone it.
     unsafe fn clone_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) -> RawWaker {
-        let waker: Arc<W> = Arc::from_raw(waker as *const W);
-        mem::forget(Arc::clone(&waker));
-        raw_waker(waker)
+        Arc::incr_strong_count(waker as *const W);
+        RawWaker::new(
+            waker as *const (),
+            &RawWakerVTable::new(clone_waker::<W>, wake::<W>, wake_by_ref::<W>, drop_waker::<W>),
+        )
     }
 
     // Wake by value, moving the Arc into the Wake::wake function
@@ -79,7 +81,7 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker {
 
     // Decrement the reference count of the Arc on drop
     unsafe fn drop_waker<W: Wake + Send + Sync + 'static>(waker: *const ()) {
-        mem::drop(Arc::from_raw(waker as *const W));
+        Arc::decr_strong_count(waker as *const W);
     }
 
     RawWaker::new(
diff --git a/src/libcore/ops/drop.rs b/src/libcore/ops/drop.rs
index 5233b475c46..06cfc363636 100644
--- a/src/libcore/ops/drop.rs
+++ b/src/libcore/ops/drop.rs
@@ -1,85 +1,139 @@
-/// Used to run some code when a value goes out of scope.
-/// This is sometimes called a 'destructor'.
+/// Custom code within the destructor.
 ///
-/// When a value goes out of scope, it will have its `drop` method called if
-/// its type implements `Drop`. Then, any fields the value contains will also
-/// be dropped recursively.
+/// When a value is no longer needed, Rust will run a "destructor" on that value.
+/// The most common way that a value is no longer needed is when it goes out of
+/// scope. Destructors may still run in other circumstances, but we're going to
+/// focus on scope for the examples here. To learn about some of those other cases,
+/// please see [the reference] section on destructors.
 ///
-/// Because of this recursive dropping, you do not need to implement this trait
-/// unless your type needs its own destructor logic.
+/// [the reference]: https://doc.rust-lang.org/reference/destructors.html
 ///
-/// Refer to [the chapter on `Drop` in *The Rust Programming Language*][book]
-/// for some more elaboration.
+/// This destructor consists of two components:
+/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type.
+/// - The automatically generated "drop glue" which recursively calls the destructors
+///     of the all fields of this value.
 ///
-/// [book]: ../../book/ch15-03-drop.html
+/// As Rust automatically calls the destructors of all contained fields,
+/// you don't have to implement `Drop` in most cases. But there are some cases where
+/// it is useful, for example for types which directly manage a resource.
+/// That resource may be memory, it may be a file descriptor, it may be a network socket.
+/// Once a value of that type is no longer going to be used, it should "clean up" its
+/// resource by freeing the memory or closing the file or socket. This is
+/// the job of a destructor, and therefore the job of `Drop::drop`.
 ///
-/// # Examples
+/// ## Examples
 ///
-/// ## Implementing `Drop`
+/// To see destructors in action, let's take a look at the following program:
 ///
-/// The `drop` method is called when `_x` goes out of scope, and therefore
-/// `main` prints `Dropping!`.
-///
-/// ```
+/// ```rust
 /// struct HasDrop;
 ///
 /// impl Drop for HasDrop {
 ///     fn drop(&mut self) {
-///         println!("Dropping!");
+///         println!("Dropping HasDrop!");
+///     }
+/// }
+///
+/// struct HasTwoDrops {
+///     one: HasDrop,
+///     two: HasDrop,
+/// }
+///
+/// impl Drop for HasTwoDrops {
+///     fn drop(&mut self) {
+///         println!("Dropping HasTwoDrops!");
 ///     }
 /// }
 ///
 /// fn main() {
-///     let _x = HasDrop;
+///     let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
+///     println!("Running!");
 /// }
 /// ```
 ///
-/// ## Dropping is done recursively
+/// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`,
+/// meaning that running this will print
 ///
-/// When `outer` goes out of scope, the `drop` method will be called first for
-/// `Outer`, then for `Inner`. Therefore, `main` prints `Dropping Outer!` and
-/// then `Dropping Inner!`.
+/// ```text
+/// Running!
+/// Dropping HasTwoDrops!
+/// Dropping HasDrop!
+/// Dropping HasDrop!
+/// ```
+///
+/// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called.
+/// This would result in
 ///
+/// ```test
+/// Running!
+/// Dropping HasDrop!
+/// Dropping HasDrop!
 /// ```
-/// struct Inner;
-/// struct Outer(Inner);
 ///
-/// impl Drop for Inner {
+/// ## You cannot call `Drop::drop` yourself
+///
+/// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after
+/// the method has been called. As `Drop::drop` does not take ownership of its input,
+/// Rust prevents misuse by not allowing you to call `Drop::drop` directly.
+///
+/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error.
+///
+/// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead.
+///
+/// [`std::mem::drop`]: ../../std/mem/fn.drop.html
+///
+/// ## Drop order
+///
+/// Which of our two `HasDrop` drops first, though? For structs, it's the same
+/// order that they're declared: first `one`, then `two`. If you'd like to try
+/// this yourself, you can modify `HasDrop` above to contain some data, like an
+/// integer, and then use it in the `println!` inside of `Drop`. This behavior is
+/// guaranteed by the language.
+///
+/// Unlike for structs, local variables are dropped in reverse order:
+///
+/// ```rust
+/// struct Foo;
+///
+/// impl Drop for Foo {
 ///     fn drop(&mut self) {
-///         println!("Dropping Inner!");
+///         println!("Dropping Foo!")
 ///     }
 /// }
 ///
-/// impl Drop for Outer {
+/// struct Bar;
+///
+/// impl Drop for Bar {
 ///     fn drop(&mut self) {
-///         println!("Dropping Outer!");
+///         println!("Dropping Bar!")
 ///     }
 /// }
 ///
 /// fn main() {
-///     let _x = Outer(Inner);
+///     let _foo = Foo;
+///     let _bar = Bar;
 /// }
 /// ```
 ///
-/// ## Variables are dropped in reverse order of declaration
-///
-/// `_first` is declared first and `_second` is declared second, so `main` will
-/// print `Declared second!` and then `Declared first!`.
+/// This will print
 ///
+/// ```text
+/// Dropping Bar!
+/// Dropping Foo!
 /// ```
-/// struct PrintOnDrop(&'static str);
 ///
-/// impl Drop for PrintOnDrop {
-///     fn drop(&mut self) {
-///         println!("{}", self.0);
-///     }
-/// }
+/// Please see [the reference] for the full rules.
 ///
-/// fn main() {
-///     let _first = PrintOnDrop("Declared first!");
-///     let _second = PrintOnDrop("Declared second!");
-/// }
-/// ```
+/// [the reference]: https://doc.rust-lang.org/reference/destructors.html
+///
+/// ## `Copy` and `Drop` are exclusive
+///
+/// You cannot implement both [`Copy`] and `Drop` on the same type. Types that
+/// are `Copy` get implicitly duplicated by the compiler, making it very
+/// hard to predict when, and how often destructors will be executed. As such,
+/// these types cannot have destructors.
+///
+/// [`Copy`]: ../../std/marker/trait.Copy.html
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 55c9f26999b..b3bb72554e9 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -13,7 +13,7 @@ use rustc_ast::util::classify;
 use rustc_ast::util::literal::LitError;
 use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::mem;
@@ -1068,8 +1068,8 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_path_start_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
-        let lo = self.token.span;
         let path = self.parse_path(PathStyle::Expr)?;
+        let lo = path.span;
 
         // `!`, as an operator, is prefix, so we know this isn't that.
         let (hi, kind) = if self.eat(&token::Not) {
@@ -1081,7 +1081,7 @@ impl<'a> Parser<'a> {
             };
             (self.prev_token.span, ExprKind::MacCall(mac))
         } else if self.check(&token::OpenDelim(token::Brace)) {
-            if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
+            if let Some(expr) = self.maybe_parse_struct_expr(&path, &attrs) {
                 return expr;
             } else {
                 (path.span, ExprKind::Path(None, path))
@@ -1895,16 +1895,15 @@ impl<'a> Parser<'a> {
 
     fn maybe_parse_struct_expr(
         &mut self,
-        lo: Span,
         path: &ast::Path,
         attrs: &AttrVec,
     ) -> Option<PResult<'a, P<Expr>>> {
         let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
         if struct_allowed || self.is_certainly_not_a_block() {
             // This is a struct literal, but we don't can't accept them here.
-            let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone());
+            let expr = self.parse_struct_expr(path.clone(), attrs.clone());
             if let (Ok(expr), false) = (&expr, struct_allowed) {
-                self.error_struct_lit_not_allowed_here(lo, expr.span);
+                self.error_struct_lit_not_allowed_here(path.span, expr.span);
             }
             return Some(expr);
         }
@@ -1923,17 +1922,23 @@ impl<'a> Parser<'a> {
 
     pub(super) fn parse_struct_expr(
         &mut self,
-        lo: Span,
         pth: ast::Path,
         mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
-        let struct_sp = lo.to(self.prev_token.span);
         self.bump();
         let mut fields = Vec::new();
         let mut base = None;
+        let mut recover_async = false;
 
         attrs.extend(self.parse_inner_attributes()?);
 
+        let mut async_block_err = |e: &mut DiagnosticBuilder<'_>, span: Span| {
+            recover_async = true;
+            e.span_label(span, "`async` blocks are only allowed in the 2018 edition");
+            e.help("set `edition = \"2018\"` in `Cargo.toml`");
+            e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+        };
+
         while self.token != token::CloseDelim(token::Brace) {
             if self.eat(&token::DotDot) {
                 let exp_span = self.prev_token.span;
@@ -1952,7 +1957,11 @@ impl<'a> Parser<'a> {
             let parsed_field = match self.parse_field() {
                 Ok(f) => Some(f),
                 Err(mut e) => {
-                    e.span_label(struct_sp, "while parsing this struct");
+                    if pth == kw::Async {
+                        async_block_err(&mut e, pth.span);
+                    } else {
+                        e.span_label(pth.span, "while parsing this struct");
+                    }
                     e.emit();
 
                     // If the next token is a comma, then try to parse
@@ -1976,15 +1985,19 @@ impl<'a> Parser<'a> {
                     }
                 }
                 Err(mut e) => {
-                    e.span_label(struct_sp, "while parsing this struct");
-                    if let Some(f) = recovery_field {
-                        fields.push(f);
-                        e.span_suggestion(
-                            self.prev_token.span.shrink_to_hi(),
-                            "try adding a comma",
-                            ",".into(),
-                            Applicability::MachineApplicable,
-                        );
+                    if pth == kw::Async {
+                        async_block_err(&mut e, pth.span);
+                    } else {
+                        e.span_label(pth.span, "while parsing this struct");
+                        if let Some(f) = recovery_field {
+                            fields.push(f);
+                            e.span_suggestion(
+                                self.prev_token.span.shrink_to_hi(),
+                                "try adding a comma",
+                                ",".into(),
+                                Applicability::MachineApplicable,
+                            );
+                        }
                     }
                     e.emit();
                     self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
@@ -1993,9 +2006,10 @@ impl<'a> Parser<'a> {
             }
         }
 
-        let span = lo.to(self.token.span);
+        let span = pth.span.to(self.token.span);
         self.expect(&token::CloseDelim(token::Brace))?;
-        Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs))
+        let expr = if recover_async { ExprKind::Err } else { ExprKind::Struct(pth, fields, base) };
+        Ok(self.mk_expr(span, expr, attrs))
     }
 
     /// Use in case of error after field-looking code: `S { foo: () with a }`.
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index e9f5f2c0dea..7fb814973e2 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -1550,7 +1550,7 @@ impl<'a> Parser<'a> {
         if span.rust_2015() {
             let diag = self.diagnostic();
             struct_span_err!(diag, span, E0670, "`async fn` is not permitted in the 2015 edition")
-                .note("to use `async fn`, switch to Rust 2018")
+                .span_label(span, "to use `async fn`, switch to Rust 2018")
                 .help("set `edition = \"2018\"` in `Cargo.toml`")
                 .note("for more on editions, read https://doc.rust-lang.org/edition-guide")
                 .emit();
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index e5d0ab247aa..849193151c3 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -79,7 +79,7 @@ impl<'a> Parser<'a> {
         }
 
         let expr = if self.check(&token::OpenDelim(token::Brace)) {
-            self.parse_struct_expr(lo, path, AttrVec::new())?
+            self.parse_struct_expr(path, AttrVec::new())?
         } else {
             let hi = self.prev_token.span;
             self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 450293b991b..8e82480c630 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -47,6 +47,7 @@ impl TypoSuggestion {
 /// A free importable items suggested in case of resolution failure.
 crate struct ImportSuggestion {
     pub did: Option<DefId>,
+    pub descr: &'static str,
     pub path: Path,
 }
 
@@ -652,7 +653,7 @@ impl<'a> Resolver<'a> {
                                 Res::Def(DefKind::Ctor(..), did) => this.parent(did),
                                 _ => res.opt_def_id(),
                             };
-                            candidates.push(ImportSuggestion { did, path });
+                            candidates.push(ImportSuggestion { did, descr: res.descr(), path });
                         }
                     }
                 }
@@ -1445,7 +1446,7 @@ fn find_span_immediately_after_crate_name(
 crate fn show_candidates(
     err: &mut DiagnosticBuilder<'_>,
     // This is `None` if all placement locations are inside expansions
-    span: Option<Span>,
+    use_placement_span: Option<Span>,
     candidates: &[ImportSuggestion],
     better: bool,
     found_use: bool,
@@ -1453,6 +1454,7 @@ crate fn show_candidates(
     if candidates.is_empty() {
         return;
     }
+
     // we want consistent results across executions, but candidates are produced
     // by iterating through a hash map, so make sure they are ordered:
     let mut path_strings: Vec<_> =
@@ -1460,14 +1462,15 @@ crate fn show_candidates(
     path_strings.sort();
     path_strings.dedup();
 
-    let better = if better { "better " } else { "" };
-    let msg_diff = match path_strings.len() {
-        1 => " is found in another module, you can import it",
-        _ => "s are found in other modules, you can import them",
+    let (determiner, kind) = if candidates.len() == 1 {
+        ("this", candidates[0].descr)
+    } else {
+        ("one of these", "items")
     };
-    let msg = format!("possible {}candidate{} into scope", better, msg_diff);
+    let instead = if better { " instead" } else { "" };
+    let msg = format!("consider importing {} {}{}", determiner, kind, instead);
 
-    if let Some(span) = span {
+    if let Some(span) = use_placement_span {
         for candidate in &mut path_strings {
             // produce an additional newline to separate the new use statement
             // from the directly following item.
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index f6213189d94..6041a56d366 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -151,7 +151,11 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
             };
             (
                 format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
-                format!("not found in {}", mod_str),
+                if path_str == "async" && expected.starts_with("struct") {
+                    "`async` blocks are only allowed in the 2018 edition".to_string()
+                } else {
+                    format!("not found in {}", mod_str)
+                },
                 item_span,
                 false,
             )
@@ -873,7 +877,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
                     let module_def_id = module.def_id().unwrap();
                     if module_def_id == def_id {
                         let path = Path { span: name_binding.span, segments: path_segments };
-                        result = Some((module, ImportSuggestion { did: Some(def_id), path }));
+                        result = Some((
+                            module,
+                            ImportSuggestion { did: Some(def_id), descr: "module", path },
+                        ));
                     } else {
                         // add the module to the lookup
                         if seen_modules.insert(module_def_id) {
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 19ed6b50f92..6c51afa9660 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1491,12 +1491,26 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             ty::Predicate::Projection(ref data) => {
                 let trait_ref = data.to_poly_trait_ref(self.tcx);
                 let self_ty = trait_ref.self_ty();
+                let ty = data.skip_binder().ty;
                 if predicate.references_error() {
                     return;
                 }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot satisfy `{}`", predicate));
-                err
+                if self_ty.needs_infer() && ty.needs_infer() {
+                    // We do this for the `foo.collect()?` case to produce a suggestion.
+                    let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                    err.note(&format!("cannot satisfy `{}`", predicate));
+                    err
+                } else {
+                    let mut err = struct_span_err!(
+                        self.tcx.sess,
+                        span,
+                        E0284,
+                        "type annotations needed: cannot satisfy `{}`",
+                        predicate,
+                    );
+                    err.span_label(span, &format!("cannot satisfy `{}`", predicate));
+                    err
+                }
             }
 
             _ => {
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
index 3aed85645ae..b8321ce5b25 100644
--- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr
+++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
@@ -1,22 +1,18 @@
-error[E0284]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
   --> $DIR/associated-types-overridden-binding.rs:4:12
    |
 LL | trait Foo: Iterator<Item = i32> {}
    |                     ---------- required by this bound in `Foo`
 LL | trait Bar: Foo<Item = u32> {}
-   |            ^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
-   |
-   = note: cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
+   |            ^^^^^^^^^^^^^^^ cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
 
-error[E0284]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
   --> $DIR/associated-types-overridden-binding.rs:7:21
    |
 LL | trait I32Iterator = Iterator<Item = i32>;
    |                              ---------- required by this bound in `I32Iterator`
 LL | trait U32Iterator = I32Iterator<Item = u32>;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
-   |
-   = note: cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Self as std::iter::Iterator>::Item == i32`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index f3d982801bb..8bffeb2131d 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -2,9 +2,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:3:1
    |
 LL | async fn foo() {}
-   | ^^^^^
+   | ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -12,9 +11,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:5:12
    |
 LL | fn baz() { async fn foo() {} }
-   |            ^^^^^
+   |            ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -22,9 +20,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:7:1
    |
 LL | async fn async_baz() {
-   | ^^^^^
+   | ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -32,9 +29,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:8:5
    |
 LL |     async fn bar() {}
-   |     ^^^^^
+   |     ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -42,9 +38,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:14:5
    |
 LL |     async fn foo() {}
-   |     ^^^^^
+   |     ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -52,9 +47,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:18:5
    |
 LL |     async fn foo() {}
-   |     ^^^^^
+   |     ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -62,9 +56,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:36:9
    |
 LL |         async fn bar() {}
-   |         ^^^^^
+   |         ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -72,9 +65,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:26:9
    |
 LL |         async fn foo() {}
-   |         ^^^^^
+   |         ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
@@ -82,9 +74,8 @@ error[E0670]: `async fn` is not permitted in the 2015 edition
   --> $DIR/edition-deny-async-fns-2015.rs:31:13
    |
 LL |             async fn bar() {}
-   |             ^^^^^
+   |             ^^^^^ to use `async fn`, switch to Rust 2018
    |
-   = note: to use `async fn`, switch to Rust 2018
    = help: set `edition = "2018"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
diff --git a/src/test/ui/class-missing-self.stderr b/src/test/ui/class-missing-self.stderr
index 681d0ffea8b..d501200d73c 100644
--- a/src/test/ui/class-missing-self.stderr
+++ b/src/test/ui/class-missing-self.stderr
@@ -10,7 +10,7 @@ error[E0425]: cannot find function `sleep` in this scope
 LL |       sleep();
    |       ^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use std::thread::sleep;
    |
diff --git a/src/test/ui/crate-in-paths.stderr b/src/test/ui/crate-in-paths.stderr
index 38d222f980d..c3aa135f77d 100644
--- a/src/test/ui/crate-in-paths.stderr
+++ b/src/test/ui/crate-in-paths.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `Foo` in this scope
 LL |     Foo;
    |     ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this unit struct
    |
 LL | use crate::bar::Foo;
    |
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
index 792b36e00bb..9429a0b5765 100644
--- a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
@@ -22,7 +22,7 @@ error[E0425]: cannot find value `Set` in this scope
 LL | fn setup() -> Set { Set }
    |                     ^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use AffixHeart::Set;
    |
diff --git a/src/test/ui/editions/async-block-2015.rs b/src/test/ui/editions/async-block-2015.rs
new file mode 100644
index 00000000000..985606a6f25
--- /dev/null
+++ b/src/test/ui/editions/async-block-2015.rs
@@ -0,0 +1,30 @@
+async fn foo() {
+//~^ ERROR `async fn` is not permitted in the 2015 edition
+//~| NOTE to use `async fn`, switch to Rust 2018
+//~| HELP set `edition = "2018"` in `Cargo.toml`
+//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+
+    let x = async {};
+    //~^ ERROR cannot find struct, variant or union type `async` in this scope
+    //~| NOTE `async` blocks are only allowed in the 2018 edition
+    let y = async { //~ NOTE `async` blocks are only allowed in the 2018 edition
+        let x = 42;
+        //~^ ERROR expected identifier, found keyword `let`
+        //~| NOTE expected identifier, found keyword
+        //~| HELP set `edition = "2018"` in `Cargo.toml`
+        //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+        42
+    };
+    let z = async { //~ NOTE `async` blocks are only allowed in the 2018 edition
+        42
+        //~^ ERROR expected identifier, found `42`
+        //~| NOTE expected identifier
+        //~| HELP set `edition = "2018"` in `Cargo.toml`
+        //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+    };
+    y.await;
+    z.await;
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/editions/async-block-2015.stderr b/src/test/ui/editions/async-block-2015.stderr
new file mode 100644
index 00000000000..8e5e5d8bfab
--- /dev/null
+++ b/src/test/ui/editions/async-block-2015.stderr
@@ -0,0 +1,41 @@
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/async-block-2015.rs:1:1
+   |
+LL | async fn foo() {
+   | ^^^^^ to use `async fn`, switch to Rust 2018
+   |
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: expected identifier, found keyword `let`
+  --> $DIR/async-block-2015.rs:11:9
+   |
+LL |     let y = async {
+   |             ----- `async` blocks are only allowed in the 2018 edition
+LL |         let x = 42;
+   |         ^^^ expected identifier, found keyword
+   |
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: expected identifier, found `42`
+  --> $DIR/async-block-2015.rs:19:9
+   |
+LL |     let z = async {
+   |             ----- `async` blocks are only allowed in the 2018 edition
+LL |         42
+   |         ^^ expected identifier
+   |
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0422]: cannot find struct, variant or union type `async` in this scope
+  --> $DIR/async-block-2015.rs:7:13
+   |
+LL |     let x = async {};
+   |             ^^^^^ `async` blocks are only allowed in the 2018 edition
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0422, E0670.
+For more information about an error, try `rustc --explain E0422`.
diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr
index efbd53fd223..995da6cc1f9 100644
--- a/src/test/ui/glob-resolve1.stderr
+++ b/src/test/ui/glob-resolve1.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `fpriv` in this scope
 LL |     fpriv();
    |     ^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use bar::fpriv;
    |
@@ -15,7 +15,7 @@ error[E0425]: cannot find function `epriv` in this scope
 LL |     epriv();
    |     ^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use bar::epriv;
    |
@@ -32,7 +32,7 @@ error[E0425]: cannot find value `C` in this scope
 LL |     C;
    |     ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this unit struct
    |
 LL | use bar::C;
    |
@@ -56,7 +56,7 @@ help: an enum with a similar name exists
    |
 LL |     foo::<B>();
    |           ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this enum
    |
 LL | use bar::A;
    |
@@ -74,7 +74,7 @@ help: an enum with a similar name exists
    |
 LL |     foo::<B>();
    |           ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL | use bar::C;
    |
@@ -92,7 +92,7 @@ help: an enum with a similar name exists
    |
 LL |     foo::<B>();
    |           ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this type alias
    |
 LL | use bar::D;
    |
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
index 153ad8cbecf..8f6b7aca8fd 100644
--- a/src/test/ui/hygiene/globs.stderr
+++ b/src/test/ui/hygiene/globs.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `f` in this scope
 LL |         f();
    |         ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing one of these items
    |
 LL | use foo::f;
    |
@@ -23,7 +23,7 @@ LL | |     }
    | |_____- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use bar::g;
    |
@@ -41,7 +41,7 @@ LL | n!(f);
 LL |         n!(f);
    |            ^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing one of these items:
            foo::f
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -54,7 +54,7 @@ LL | n!(f);
 LL |                 f
    |                 ^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing one of these items:
            foo::f
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
index 32b638dc465..3b1a5e5f4ad 100644
--- a/src/test/ui/impl-trait/universal_wrong_bounds.stderr
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
@@ -4,7 +4,7 @@ error[E0404]: expected trait, found derive macro `Debug`
 LL | fn wants_debug(g: impl Debug) { }
    |                        ^^^^^ not a trait
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this trait instead
    |
 LL | use std::fmt::Debug;
    |
@@ -15,7 +15,7 @@ error[E0404]: expected trait, found derive macro `Debug`
 LL | fn wants_display(g: impl Debug) { }
    |                          ^^^^^ not a trait
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this trait instead
    |
 LL | use std::fmt::Debug;
    |
diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr
index 434c5de2874..30cb7a1df80 100644
--- a/src/test/ui/issues/issue-12028.stderr
+++ b/src/test/ui/issues/issue-12028.stderr
@@ -1,10 +1,8 @@
-error[E0284]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
   --> $DIR/issue-12028.rs:27:14
    |
 LL |         self.input_stream(&mut stream);
-   |              ^^^^^^^^^^^^ cannot infer type for type parameter `H` declared on the trait `StreamHash`
-   |
-   = note: cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
+   |              ^^^^^^^^^^^^ cannot satisfy `<_ as StreamHasher>::S == <H as StreamHasher>::S`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 1236bbcdbf6..8bf40790f0b 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -24,7 +24,7 @@ error[E0573]: expected type, found variant `Result`
 LL |     fn new() -> Result<foo::MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL |     use std::fmt::Result;
    |
@@ -42,7 +42,7 @@ error[E0573]: expected type, found variant `Result`
 LL | fn new() -> Result<foo::MyEnum, String> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use std::fmt::Result;
    |
diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr
index a9a27da55b1..8637e574c5e 100644
--- a/src/test/ui/issues/issue-35675.stderr
+++ b/src/test/ui/issues/issue-35675.stderr
@@ -15,7 +15,7 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Apple` in thi
 LL |     Apple(5)
    |     ^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this tuple variant
    |
 LL | use Fruit::Apple;
    |
@@ -35,7 +35,7 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Apple` in thi
 LL |     Apple(5)
    |     ^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this tuple variant
    |
 LL | use Fruit::Apple;
    |
diff --git a/src/test/ui/issues/issue-37534.stderr b/src/test/ui/issues/issue-37534.stderr
index b82e7b38914..5d008cf24dc 100644
--- a/src/test/ui/issues/issue-37534.stderr
+++ b/src/test/ui/issues/issue-37534.stderr
@@ -4,7 +4,7 @@ error[E0404]: expected trait, found derive macro `Hash`
 LL | struct Foo<T: ?Hash> { }
    |                ^^^^ not a trait
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this trait instead
    |
 LL | use std::hash::Hash;
    |
diff --git a/src/test/ui/issues/issue-38293.stderr b/src/test/ui/issues/issue-38293.stderr
index cc3c72b496f..d2450ab1250 100644
--- a/src/test/ui/issues/issue-38293.stderr
+++ b/src/test/ui/issues/issue-38293.stderr
@@ -10,7 +10,7 @@ error[E0423]: expected function, found module `baz`
 LL |     baz();
    |     ^^^ not a function
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this function instead
    |
 LL | use bar::baz;
    |
diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr
index c71194f41c1..e7e251e39c0 100644
--- a/src/test/ui/issues/issue-42944.stderr
+++ b/src/test/ui/issues/issue-42944.stderr
@@ -10,7 +10,7 @@ error[E0425]: cannot find function, tuple struct or tuple variant `B` in this sc
 LL |         B(());
    |         ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this tuple struct
    |
 LL |     use foo::B;
    |
diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr
index 60a1155c614..ecee595d4ab 100644
--- a/src/test/ui/issues/issue-4366-2.stderr
+++ b/src/test/ui/issues/issue-4366-2.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Bar` in this scope
 LL |         fn sub() -> Bar { 1 }
    |                     ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this type alias
    |
 LL |         use a::b::Bar;
    |
@@ -15,7 +15,7 @@ error[E0423]: expected function, found module `foo`
 LL |     foo();
    |     ^^^ not a function
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use foo::foo;
    |
diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr
index d931d519117..a094180572d 100644
--- a/src/test/ui/issues/issue-4366.stderr
+++ b/src/test/ui/issues/issue-4366.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `foo` in this scope
 LL |         fn sub() -> isize { foo(); 1 }
    |                             ^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use foo::foo;
    |
diff --git a/src/test/ui/issues/issue-50599.stderr b/src/test/ui/issues/issue-50599.stderr
index 378c57011ac..7ec567a06f0 100644
--- a/src/test/ui/issues/issue-50599.stderr
+++ b/src/test/ui/issues/issue-50599.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64`
 LL |     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
    |                                                ^^^^^^^ not found in `std::f64`
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use std::f32::consts::LOG10_2;
    |
diff --git a/src/test/ui/issues/issue-69455.rs b/src/test/ui/issues/issue-69455.rs
index 017654554be..f1935ae2534 100644
--- a/src/test/ui/issues/issue-69455.rs
+++ b/src/test/ui/issues/issue-69455.rs
@@ -26,5 +26,5 @@ impl Test<u64> for u64 {
 
 fn main() {
     let xs: Vec<u64> = vec![1, 2, 3];
-    println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed [E0284]
+    println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed
 }
diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr
index 4caa1aca9fd..430bbcabf83 100644
--- a/src/test/ui/issues/issue-69455.stderr
+++ b/src/test/ui/issues/issue-69455.stderr
@@ -1,16 +1,8 @@
-error[E0284]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<u64 as Test<_>>::Output == _`
   --> $DIR/issue-69455.rs:29:26
    |
-LL |     type Output;
-   |     ------------ `<Self as Test<Rhs>>::Output` defined here
-...
 LL |     println!("{}", 23u64.test(xs.iter().sum()));
-   |                    ------^^^^-----------------
-   |                    |     |
-   |                    |     cannot infer type for type `u64`
-   |                    this method call resolves to `<Self as Test<Rhs>>::Output`
-   |
-   = note: cannot satisfy `<u64 as Test<_>>::Output == _`
+   |                          ^^^^ cannot satisfy `<u64 as Test<_>>::Output == _`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-69683.rs b/src/test/ui/issues/issue-69683.rs
new file mode 100644
index 00000000000..cc7f1fa0f55
--- /dev/null
+++ b/src/test/ui/issues/issue-69683.rs
@@ -0,0 +1,32 @@
+pub trait Element<S> {
+    type Array;
+}
+
+impl<T> Element<()> for T {
+    type Array = T;
+}
+
+impl<T: Element<S>, S> Element<[S; 3]> for T {
+    type Array = [T::Array; 3];
+}
+
+trait Foo<I>
+where
+    u8: Element<I>,
+{
+    fn foo(self, x: <u8 as Element<I>>::Array);
+}
+
+impl<I> Foo<I> for u16
+where
+    u8: Element<I>,
+{
+    fn foo(self, _: <u8 as Element<I>>::Array) {}
+}
+
+fn main() {
+    let b: [u8; 3] = [0u8; 3];
+
+    0u16.foo(b); //~ ERROR type annotations needed
+    //<u16 as Foo<[(); 3]>>::foo(0u16, b);
+}
diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr
new file mode 100644
index 00000000000..776370331a4
--- /dev/null
+++ b/src/test/ui/issues/issue-69683.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
+  --> $DIR/issue-69683.rs:30:10
+   |
+LL |     0u16.foo(b);
+   |          ^^^ cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/issues/issue-71584.rs b/src/test/ui/issues/issue-71584.rs
new file mode 100644
index 00000000000..c96cd598f0c
--- /dev/null
+++ b/src/test/ui/issues/issue-71584.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let n: u32 = 1;
+    let mut d: u64 = 2;
+    d = d % n.into(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/issues/issue-71584.stderr b/src/test/ui/issues/issue-71584.stderr
new file mode 100644
index 00000000000..c162d338a93
--- /dev/null
+++ b/src/test/ui/issues/issue-71584.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `<u64 as std::ops::Rem<_>>::Output == u64`
+  --> $DIR/issue-71584.rs:4:11
+   |
+LL |     d = d % n.into();
+   |           ^ cannot satisfy `<u64 as std::ops::Rem<_>>::Output == u64`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index 6bb0877e9b9..dce70545170 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found type parameter `T`
 LL |     let t = T { i: 0 };
    |             ^ not a struct, variant or union type
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this struct instead
    |
 LL | use T;
    |
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index 1d0b2a554f1..d0d91bb61f4 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -94,7 +94,7 @@ mod foo {
   ],
   "children": [
     {
-      "message": "possible candidates are found in other modules, you can import them into scope",
+      "message": "consider importing one of these items",
       "code": null,
       "level": "help",
       "spans": [
@@ -385,7 +385,7 @@ mod foo {
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m    let x: Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m           \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
-\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: possible candidates are found in other modules, you can import them into scope\u001b[0m
+\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::binary_heap::Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
diff --git a/src/test/ui/macros/macro-outer-attributes.stderr b/src/test/ui/macros/macro-outer-attributes.stderr
index 86a6baca053..8e064d980af 100644
--- a/src/test/ui/macros/macro-outer-attributes.stderr
+++ b/src/test/ui/macros/macro-outer-attributes.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `bar` in module `a`
 LL |     a::bar();
    |        ^^^ not found in `a`
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use b::bar;
    |
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index f82c83fd5b0..c80055f00d7 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -12,7 +12,7 @@ help: a tuple struct with a similar name exists
    |
 LL |     check(m1::TS);
    |               ^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use m2::S;
    |
@@ -35,7 +35,7 @@ help: a tuple struct with a similar name exists
    |
 LL |     check(xm1::TS);
    |                ^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use m2::S;
    |
@@ -57,7 +57,7 @@ help: a tuple variant with a similar name exists
    |
 LL |     check(m7::TV);
    |               ^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use m8::V;
    |
@@ -79,7 +79,7 @@ help: a tuple variant with a similar name exists
    |
 LL |     check(xm7::TV);
    |                ^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use m8::V;
    |
diff --git a/src/test/ui/no-implicit-prelude-nested.stderr b/src/test/ui/no-implicit-prelude-nested.stderr
index e57d8af5f99..8a26366d751 100644
--- a/src/test/ui/no-implicit-prelude-nested.stderr
+++ b/src/test/ui/no-implicit-prelude-nested.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Add` in this scope
 LL |         impl Add for Test {}
    |              ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL |         use std::ops::Add;
    |
@@ -15,7 +15,7 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL |         use std::clone::Clone;
    |
@@ -28,7 +28,7 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::iter::Iterator;
    |
@@ -41,7 +41,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::prelude::v1::ToString;
    |
@@ -60,7 +60,7 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::mem::drop;
    |
@@ -73,7 +73,7 @@ error[E0405]: cannot find trait `Add` in this scope
 LL |     impl Add for Test {}
    |          ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL |     use std::ops::Add;
    |
@@ -84,7 +84,7 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |     impl Clone for Test {}
    |          ^^^^^ not a trait
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL |     use std::clone::Clone;
    |
@@ -97,7 +97,7 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |     impl Iterator for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |     use std::iter::Iterator;
    |
@@ -110,7 +110,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |     impl ToString for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |     use std::prelude::v1::ToString;
    |
@@ -129,7 +129,7 @@ error[E0425]: cannot find function `drop` in this scope
 LL |         drop(2)
    |         ^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |     use std::mem::drop;
    |
@@ -142,7 +142,7 @@ error[E0405]: cannot find trait `Add` in this scope
 LL |         impl Add for Test {}
    |              ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL |         use std::ops::Add;
    |
@@ -153,7 +153,7 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL |         use std::clone::Clone;
    |
@@ -166,7 +166,7 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::iter::Iterator;
    |
@@ -179,7 +179,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::prelude::v1::ToString;
    |
@@ -198,7 +198,7 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL |         use std::mem::drop;
    |
diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/no-implicit-prelude.stderr
index 8b99529f4dd..9cda4f64c79 100644
--- a/src/test/ui/no-implicit-prelude.stderr
+++ b/src/test/ui/no-implicit-prelude.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Add` in this scope
 LL | impl Add for Test {}
    |      ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL | use std::ops::Add;
    |
@@ -15,7 +15,7 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL | impl Clone for Test {}
    |      ^^^^^ not a trait
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use std::clone::Clone;
    |
@@ -28,7 +28,7 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL | impl Iterator for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use std::iter::Iterator;
    |
@@ -41,7 +41,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL | impl ToString for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use std::prelude::v1::ToString;
    |
@@ -60,7 +60,7 @@ error[E0425]: cannot find function `drop` in this scope
 LL |     drop(2)
    |     ^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use std::mem::drop;
    |
diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr
index 90f81c64835..5d4db8c31a2 100644
--- a/src/test/ui/parser/circular_modules_main.stderr
+++ b/src/test/ui/parser/circular_modules_main.stderr
@@ -10,7 +10,7 @@ error[E0425]: cannot find function `say_hello` in module `circular_modules_hello
 LL |     circular_modules_hello::say_hello();
    |                             ^^^^^^^^^ not found in `circular_modules_hello`
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use circular_modules_hello::say_hello;
    |
diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr
index 45ca00f55ab..4d2af735fa6 100644
--- a/src/test/ui/privacy/privacy-ns1.stderr
+++ b/src/test/ui/privacy/privacy-ns1.stderr
@@ -11,7 +11,7 @@ help: a unit struct with a similar name exists
    |
 LL |     Baz();
    |     ^^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use foo1::Bar;
    |
@@ -33,7 +33,7 @@ help: a unit struct with a similar name exists
    |
 LL |     Baz();
    |     ^^^
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use foo1::Bar;
    |
@@ -55,7 +55,7 @@ help: a struct with a similar name exists
    |
 LL |     let _x: Box<Baz>;
    |                 ^^^
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use foo1::Bar;
    |
diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr
index 0c826147a1c..f1aa523742a 100644
--- a/src/test/ui/privacy/privacy-ns2.stderr
+++ b/src/test/ui/privacy/privacy-ns2.stderr
@@ -4,7 +4,7 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar
 LL |     Bar();
    |     ^^^ not a function, tuple struct or tuple variant
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use foo1::Bar;
    |
@@ -26,7 +26,7 @@ help: a unit struct with a similar name exists
    |
 LL |     Baz();
    |     ^^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use foo1::Bar;
    |
@@ -45,7 +45,7 @@ help: use `=` if you meant to assign
    |
 LL |     let _x = Bar();
    |            ^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use foo1::Bar;
    |
diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
index f0ab107e151..b37f1bd393c 100644
--- a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
+++ b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
@@ -50,7 +50,7 @@ help: a type alias with a similar name exists
    |
 LL |     type A = A;
    |              ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL |     use Y;
    |
@@ -65,7 +65,7 @@ help: a type alias with a similar name exists
    |
 LL | type A = A;
    |          ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL | use m::X;
    |
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index 5a329639e8e..9b946b5e244 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `FromOutside` in this scope
 LL | generate_mod::check!();
    | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing this struct:
            FromOutside
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -14,7 +14,7 @@ error[E0412]: cannot find type `Outer` in this scope
 LL | generate_mod::check!();
    | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing this struct:
            Outer
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -24,7 +24,7 @@ error[E0412]: cannot find type `FromOutside` in this scope
 LL | #[generate_mod::check_attr]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing this struct:
            FromOutside
    = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -34,7 +34,7 @@ error[E0412]: cannot find type `OuterAttr` in this scope
 LL | #[generate_mod::check_attr]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
    |
-   = note: possible candidate is found in another module, you can import it into scope:
+   = note: consider importing this struct:
            OuterAttr
    = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr
index 30a4cd7c116..81d2113c3b2 100644
--- a/src/test/ui/proc-macro/mixed-site-span.stderr
+++ b/src/test/ui/proc-macro/mixed-site-span.stderr
@@ -27,7 +27,7 @@ LL | pass_dollar_crate!();
    | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL | use ItemUse;
    |
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
index 61816709ecc..621686dd292 100644
--- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr
+++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `A` in crate `namespaced_enums`
 LL |     let _ = namespaced_enums::A;
    |                               ^ not found in `namespaced_enums`
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this unit variant
    |
 LL | use namespaced_enums::Foo::A;
    |
@@ -15,7 +15,7 @@ error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `
 LL |     let _ = namespaced_enums::B(10);
    |                               ^ not found in `namespaced_enums`
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this tuple variant
    |
 LL | use namespaced_enums::Foo::B;
    |
@@ -26,7 +26,7 @@ error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced
 LL |     let _ = namespaced_enums::C { a: 10 };
    |                               ^ not found in `namespaced_enums`
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this variant
    |
 LL | use namespaced_enums::Foo::C;
    |
diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr
index 913009ce51c..c47d22cef5f 100644
--- a/src/test/ui/resolve/issue-16058.stderr
+++ b/src/test/ui/resolve/issue-16058.stderr
@@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found enum `Result`
 LL |         Result {
    |         ^^^^^^ not a struct, variant or union type
    |
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use std::fmt::Result;
    |
diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr
index 6098d4f4901..034d0d01bfb 100644
--- a/src/test/ui/resolve/issue-17518.stderr
+++ b/src/test/ui/resolve/issue-17518.stderr
@@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope
 LL |     E { name: "foobar" };
    |     ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this variant
    |
 LL | use SomeEnum::E;
    |
diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr
index 27fd612faca..d3e19534353 100644
--- a/src/test/ui/resolve/issue-21221-1.stderr
+++ b/src/test/ui/resolve/issue-21221-1.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Mul` in this scope
 LL | impl Mul for Foo {
    |      ^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use mul1::Mul;
    |
@@ -19,7 +19,7 @@ error[E0412]: cannot find type `Mul` in this scope
 LL | fn getMul() -> Mul {
    |                ^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use mul1::Mul;
    |
@@ -43,7 +43,7 @@ error[E0405]: cannot find trait `Div` in this scope
 LL | impl Div for Foo {
    |      ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL | use std::ops::Div;
    |
diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr
index b360fda6f9d..f9263d2af50 100644
--- a/src/test/ui/resolve/issue-21221-2.stderr
+++ b/src/test/ui/resolve/issue-21221-2.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope
 LL | impl T for Foo { }
    |      ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL | use foo::bar::T;
    |
diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr
index f2c94d467e2..f12e5b09bac 100644
--- a/src/test/ui/resolve/issue-21221-3.stderr
+++ b/src/test/ui/resolve/issue-21221-3.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `OuterTrait` in this scope
 LL | impl OuterTrait for Foo {}
    |      ^^^^^^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL | use issue_21221_3::outer::OuterTrait;
    |
diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr
index 0b1527f91bd..fc15444d0c0 100644
--- a/src/test/ui/resolve/issue-21221-4.stderr
+++ b/src/test/ui/resolve/issue-21221-4.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope
 LL | impl T for Foo {}
    |      ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this trait
    |
 LL | use issue_21221_4::T;
    |
diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr
index 16436a9accc..4d0b0af58a3 100644
--- a/src/test/ui/resolve/issue-3907.stderr
+++ b/src/test/ui/resolve/issue-3907.stderr
@@ -9,7 +9,7 @@ help: you might have meant to use `#![feature(trait_alias)]` instead of a `type`
    |
 LL | type Foo = dyn issue_3907::Foo;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this trait instead
    |
 LL | use issue_3907::Foo;
    |
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 30ac783ea2f..d9b1b9c5955 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -67,7 +67,7 @@ LL |     let _: E = E::Struct;
    |                ^^^^^^^^^
 LL |     let _: E = E::Unit;
    |                ^^^^^^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use std::f32::consts::E;
    |
@@ -99,7 +99,7 @@ LL |     let _: E = E::Struct;
    |                ^^^^^^^^^
 LL |     let _: E = E::Unit;
    |                ^^^^^^^
-help: possible better candidates are found in other modules, you can import them into scope
+help: consider importing one of these items instead
    |
 LL | use std::f32::consts::E;
    |
@@ -130,7 +130,7 @@ help: an enum with a similar name exists
    |
 LL |     let _: E = m::n::Z;
    |            ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this enum
    |
 LL | use m::n::Z;
    |
@@ -163,7 +163,7 @@ help: an enum with a similar name exists
    |
 LL |     let _: E = m::n::Z::Fn;
    |            ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this enum
    |
 LL | use m::n::Z;
    |
@@ -181,7 +181,7 @@ help: an enum with a similar name exists
    |
 LL |     let _: E = m::n::Z::Struct;
    |            ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this enum
    |
 LL | use m::n::Z;
    |
@@ -210,7 +210,7 @@ help: an enum with a similar name exists
    |
 LL |     let _: E = m::n::Z::Unit {};
    |            ^
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this enum
    |
 LL | use m::n::Z;
    |
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index baf7dd84eb0..e0305b129a8 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -33,7 +33,7 @@ error[E0423]: expected value, found struct `xcrate::S`
 LL |     xcrate::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
+help: consider importing this tuple struct instead
    |
 LL | use m::S;
    |
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 9d381a8a94e..8611306e82d 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -10,7 +10,7 @@ error[E0412]: cannot find type `u8` in the crate root
 LL |     let _: ::u8;
    |              ^^ not found in the crate root
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this builtin type
    |
 LL | use std::primitive::u8;
    |
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
index ef451ea847a..9c337f515ad 100644
--- a/src/test/ui/resolve/use_suggestion_placement.stderr
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Path` in this scope
 LL |     type Bar = Path;
    |                ^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL |     use std::path::Path;
    |
@@ -15,7 +15,7 @@ error[E0425]: cannot find value `A` in this scope
 LL |     let _ = A;
    |             ^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this constant
    |
 LL | use m::A;
    |
@@ -26,7 +26,7 @@ error[E0412]: cannot find type `HashMap` in this scope
 LL |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use std::collections::HashMap;
    |
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
index c712fd048f1..38cd9713d1a 100644
--- a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
+++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
@@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope
 LL |     let _d = Drain {};
    |              ^^^^^ not found in this scope
    |
-help: possible candidates are found in other modules, you can import them into scope
+help: consider importing one of these items
    |
 LL | use crate::plumbing::Drain;
    |
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
index fa603276c8e..7997cdc2957 100644
--- a/src/test/ui/self/self_type_keyword.stderr
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -66,7 +66,7 @@ error[E0531]: cannot find unit struct, unit variant or constant `Self` in this s
 LL |         mut Self => (),
    |             ^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this unit struct
    |
 LL | use foo::Self;
    |
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index 3245d8655e8..2bc3ff4c3b6 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -4,7 +4,7 @@ error[E0404]: expected trait, found type parameter `Add`
 LL | impl<T: Clone, Add> Add for Foo<T> {
    |                     ^^^ not a trait
    |
-help: possible better candidate is found in another module, you can import it into scope
+help: consider importing this trait instead
    |
 LL | use std::ops::Add;
    |
diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.stderr b/src/test/ui/suggestions/no-extern-crate-in-type.stderr
index 22aad3b0a9f..876eef2b624 100644
--- a/src/test/ui/suggestions/no-extern-crate-in-type.stderr
+++ b/src/test/ui/suggestions/no-extern-crate-in-type.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope
 LL | type Output = Option<Foo>;
    |                      ^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this struct
    |
 LL | use foo::Foo;
    |
diff --git a/src/test/ui/suggestions/raw-name-use-suggestion.stderr b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
index 62b76318e09..7447cf87ce1 100644
--- a/src/test/ui/suggestions/raw-name-use-suggestion.stderr
+++ b/src/test/ui/suggestions/raw-name-use-suggestion.stderr
@@ -26,7 +26,7 @@ error[E0425]: cannot find function `r#break` in this scope
 LL |     r#break();
    |     ^^^^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL | use foo::r#break;
    |
diff --git a/src/test/ui/use/use-super-global-path.stderr b/src/test/ui/use/use-super-global-path.stderr
index 7f98ac7cd0f..edde26c1fc1 100644
--- a/src/test/ui/use/use-super-global-path.stderr
+++ b/src/test/ui/use/use-super-global-path.stderr
@@ -22,7 +22,7 @@ error[E0425]: cannot find function `main` in this scope
 LL |         main();
    |         ^^^^ not found in this scope
    |
-help: possible candidate is found in another module, you can import it into scope
+help: consider importing this function
    |
 LL |     use main;
    |