about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-10 13:05:05 +0000
committerbors <bors@rust-lang.org>2020-04-10 13:05:05 +0000
commitdbc3cfdd25ccd56edf3ea364f86ab32967636c26 (patch)
treea75c01452eed404a4610f586ab4efd89938b6107
parent167510f776891f2b0b18d1168ed42377a63493a7 (diff)
parent68e0e6ba848087734be581afe5478635a647aa7c (diff)
downloadrust-dbc3cfdd25ccd56edf3ea364f86ab32967636c26.tar.gz
rust-dbc3cfdd25ccd56edf3ea364f86ab32967636c26.zip
Auto merge of #70983 - Centril:rollup-npabk7c, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #70784 (Consider methods on fundamental `impl` when method is not found on numeric type)
 - #70843 (Remove the Ord bound that was plaguing drain_filter)
 - #70913 (Replace "rc"/"arc" lang items with Rc/Arc diagnostic items.)
 - #70932 (De-abuse TyKind::Error in pattern type checking)
 - #70952 (Clean up E0511 explanation)
 - #70964 (rustc_session CLI lint parsing: mark a temporary hack as such)
 - #70969 (Fix JSON file_name documentation for macros.)
 - #70975 (Fix internal doc comment nits.)

Failed merges:

r? @ghost
-rw-r--r--src/doc/rustc/src/json.md7
-rw-r--r--src/liballoc/collections/btree/map.rs41
-rw-r--r--src/liballoc/collections/btree/set.rs25
-rw-r--r--src/liballoc/rc.rs3
-rw-r--r--src/liballoc/sync.rs3
-rw-r--r--src/librustc_error_codes/error_codes/E0152.md4
-rw-r--r--src/librustc_error_codes/error_codes/E0511.md5
-rw-r--r--src/librustc_error_codes/error_codes/E0718.md2
-rw-r--r--src/librustc_hir/lang_items.rs3
-rw-r--r--src/librustc_middle/ty/context.rs6
-rw-r--r--src/librustc_middle/ty/mod.rs23
-rw-r--r--src/librustc_middle/ty/sty.rs18
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mod.rs30
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/move_errors.rs5
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs2
-rw-r--r--src/librustc_session/config.rs4
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs12
-rw-r--r--src/librustc_typeck/check/method/suggest.rs28
-rw-r--r--src/librustc_typeck/check/mod.rs8
-rw-r--r--src/librustc_typeck/check/pat.rs38
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/test/ui/error-codes/E0152.rs2
-rw-r--r--src/test/ui/error-codes/E0152.stderr2
-rw-r--r--src/test/ui/error-codes/E0718.rs4
-rw-r--r--src/test/ui/error-codes/E0718.stderr6
-rw-r--r--src/test/ui/issues/issue-29181.rs2
-rw-r--r--src/test/ui/issues/issue-29181.stderr16
28 files changed, 150 insertions, 153 deletions
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
index c46380f1505..5dee603142d 100644
--- a/src/doc/rustc/src/json.md
+++ b/src/doc/rustc/src/json.md
@@ -59,8 +59,11 @@ Diagnostics have the following format:
     "spans": [
         {
             /* The file where the span is located.
-               For spans located within a macro expansion, this will be the
-               name of the expanded macro in the format "<MACRONAME macros>".
+               Note that this path may not exist. For example, if the path
+               points to the standard library, and the rust src is not
+               available in the sysroot, then it may point to a non-existent
+               file. Beware that this may also point to the source of an
+               external crate.
             */
             "file_name": "lib.rs",
             /* The byte offset where the span starts (0-based, inclusive). */
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index a1e59b2e6af..fc7e91ce47b 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -1727,28 +1727,22 @@ impl<K, V> Clone for Values<'_, K, V> {
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
 pub struct DrainFilter<'a, K, V, F>
 where
-    K: 'a + Ord, // This Ord bound should be removed before stabilization.
+    K: 'a,
     V: 'a,
     F: 'a + FnMut(&K, &mut V) -> bool,
 {
     pred: F,
     inner: DrainFilterInner<'a, K, V>,
 }
-pub(super) struct DrainFilterInner<'a, K, V>
-where
-    K: 'a + Ord,
-    V: 'a,
-{
+pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
     length: &'a mut usize,
     cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F>
+impl<K, V, F> Drop for DrainFilter<'_, K, V, F>
 where
-    K: 'a + Ord,
-    V: 'a,
-    F: 'a + FnMut(&K, &mut V) -> bool,
+    F: FnMut(&K, &mut V) -> bool,
 {
     fn drop(&mut self) {
         self.for_each(drop);
@@ -1756,11 +1750,11 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, K, V, F> fmt::Debug for DrainFilter<'a, K, V, F>
+impl<K, V, F> fmt::Debug for DrainFilter<'_, K, V, F>
 where
-    K: 'a + fmt::Debug + Ord,
-    V: 'a + fmt::Debug,
-    F: 'a + FnMut(&K, &mut V) -> bool,
+    K: fmt::Debug,
+    V: fmt::Debug,
+    F: FnMut(&K, &mut V) -> bool,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("DrainFilter").field(&self.inner.peek()).finish()
@@ -1768,11 +1762,9 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, K, V, F> Iterator for DrainFilter<'a, K, V, F>
+impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
 where
-    K: 'a + Ord,
-    V: 'a,
-    F: 'a + FnMut(&K, &mut V) -> bool,
+    F: FnMut(&K, &mut V) -> bool,
 {
     type Item = (K, V);
 
@@ -1785,11 +1777,7 @@ where
     }
 }
 
-impl<'a, K, V> DrainFilterInner<'a, K, V>
-where
-    K: 'a + Ord,
-    V: 'a,
-{
+impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
     /// Allow Debug implementations to predict the next element.
     pub(super) fn peek(&self) -> Option<(&K, &V)> {
         let edge = self.cur_leaf_edge.as_ref()?;
@@ -1828,12 +1816,7 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F>
-where
-    K: Ord,
-    F: FnMut(&K, &mut V) -> bool,
-{
-}
+impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
 
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> Iterator for Range<'a, K, V> {
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index 0b02223def4..9bf483f269f 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -1094,7 +1094,7 @@ impl<'a, T> IntoIterator for &'a BTreeSet<T> {
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
 pub struct DrainFilter<'a, T, F>
 where
-    T: 'a + Ord,
+    T: 'a,
     F: 'a + FnMut(&T) -> bool,
 {
     pred: F,
@@ -1102,10 +1102,9 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, T, F> Drop for DrainFilter<'a, T, F>
+impl<T, F> Drop for DrainFilter<'_, T, F>
 where
-    T: 'a + Ord,
-    F: 'a + FnMut(&T) -> bool,
+    F: FnMut(&T) -> bool,
 {
     fn drop(&mut self) {
         self.for_each(drop);
@@ -1113,10 +1112,10 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, T, F> fmt::Debug for DrainFilter<'a, T, F>
+impl<T, F> fmt::Debug for DrainFilter<'_, T, F>
 where
-    T: 'a + Ord + fmt::Debug,
-    F: 'a + FnMut(&T) -> bool,
+    T: fmt::Debug,
+    F: FnMut(&T) -> bool,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple("DrainFilter").field(&self.inner.peek().map(|(k, _)| k)).finish()
@@ -1124,10 +1123,9 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, 'f, T, F> Iterator for DrainFilter<'a, T, F>
+impl<'a, T, F> Iterator for DrainFilter<'_, T, F>
 where
-    T: 'a + Ord,
-    F: 'a + 'f + FnMut(&T) -> bool,
+    F: 'a + FnMut(&T) -> bool,
 {
     type Item = T;
 
@@ -1143,12 +1141,7 @@ where
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
-impl<'a, T, F> FusedIterator for DrainFilter<'a, T, F>
-where
-    T: 'a + Ord,
-    F: 'a + FnMut(&T) -> bool,
-{
-}
+impl<T, F> FusedIterator for DrainFilter<'_, T, F> where F: FnMut(&T) -> bool {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Extend<T> for BTreeSet<T> {
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 9db997e8641..abc4056cf56 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -279,7 +279,8 @@ struct RcBox<T: ?Sized> {
 /// type `T`.
 ///
 /// [get_mut]: #method.get_mut
-#[cfg_attr(not(test), lang = "rc")]
+#[cfg_attr(all(bootstrap, not(test)), lang = "rc")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
     ptr: NonNull<RcBox<T>>,
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 1cfb26eb35a..b1b22e46a7c 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -207,7 +207,8 @@ macro_rules! acquire {
 /// counting in general.
 ///
 /// [rc_examples]: ../../std/rc/index.html#examples
-#[cfg_attr(not(test), lang = "arc")]
+#[cfg_attr(all(bootstrap, not(test)), lang = "arc")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T: ?Sized> {
     ptr: NonNull<ArcInner<T>>,
diff --git a/src/librustc_error_codes/error_codes/E0152.md b/src/librustc_error_codes/error_codes/E0152.md
index 602dcb6e2c5..120c96b4211 100644
--- a/src/librustc_error_codes/error_codes/E0152.md
+++ b/src/librustc_error_codes/error_codes/E0152.md
@@ -5,8 +5,8 @@ Erroneous code example:
 ```compile_fail,E0152
 #![feature(lang_items)]
 
-#[lang = "arc"]
-struct Foo; // error: duplicate lang item found: `arc`
+#[lang = "owned_box"]
+struct Foo; // error: duplicate lang item found: `owned_box`
 ```
 
 Lang items are already implemented in the standard library. Unless you are
diff --git a/src/librustc_error_codes/error_codes/E0511.md b/src/librustc_error_codes/error_codes/E0511.md
index 4f6644f3582..5351a685eb5 100644
--- a/src/librustc_error_codes/error_codes/E0511.md
+++ b/src/librustc_error_codes/error_codes/E0511.md
@@ -1,5 +1,6 @@
-Invalid monomorphization of an intrinsic function was used. Erroneous code
-example:
+Invalid monomorphization of an intrinsic function was used.
+
+Erroneous code example:
 
 ```compile_fail,E0511
 #![feature(platform_intrinsics)]
diff --git a/src/librustc_error_codes/error_codes/E0718.md b/src/librustc_error_codes/error_codes/E0718.md
index 8548ff0c150..e7ae51ca588 100644
--- a/src/librustc_error_codes/error_codes/E0718.md
+++ b/src/librustc_error_codes/error_codes/E0718.md
@@ -6,6 +6,6 @@ Examples of erroneous code:
 ```compile_fail,E0718
 #![feature(lang_items)]
 
-#[lang = "arc"]
+#[lang = "owned_box"]
 static X: u32 = 42;
 ```
diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs
index 89457009a8b..5a3a9cabeb4 100644
--- a/src/librustc_hir/lang_items.rs
+++ b/src/librustc_hir/lang_items.rs
@@ -254,7 +254,4 @@ language_item_table! {
     AlignOffsetLangItem,         "align_offset",       align_offset_fn,         Target::Fn;
 
     TerminationTraitLangItem,    "termination",        termination,             Target::Trait;
-
-    Arc,                         "arc",                arc,                     Target::Struct;
-    Rc,                          "rc",                 rc,                      Target::Struct;
 }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 6e504a107a3..b336a30e3d3 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -2210,6 +2210,12 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
+    pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
+        let def_id = self.get_diagnostic_item(name)?;
+        Some(self.mk_generic_adt(def_id, ty))
+    }
+
+    #[inline]
     pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None);
         self.mk_generic_adt(def_id, ty)
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 18518e78e35..8dbf27b0ed8 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -1829,14 +1829,9 @@ bitflags! {
         const IS_BOX              = 1 << 6;
         /// Indicates whether the type is `ManuallyDrop`.
         const IS_MANUALLY_DROP    = 1 << 7;
-        // FIXME(matthewjasper) replace these with diagnostic items
-        /// Indicates whether the type is an `Arc`.
-        const IS_ARC              = 1 << 8;
-        /// Indicates whether the type is an `Rc`.
-        const IS_RC               = 1 << 9;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 10;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
     }
 }
 
@@ -2221,12 +2216,6 @@ impl<'tcx> AdtDef {
         if Some(did) == tcx.lang_items().manually_drop() {
             flags |= AdtFlags::IS_MANUALLY_DROP;
         }
-        if Some(did) == tcx.lang_items().arc() {
-            flags |= AdtFlags::IS_ARC;
-        }
-        if Some(did) == tcx.lang_items().rc() {
-            flags |= AdtFlags::IS_RC;
-        }
 
         AdtDef { did, variants, flags, repr }
     }
@@ -2305,16 +2294,6 @@ impl<'tcx> AdtDef {
         self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
     }
 
-    /// Returns `true` if this is `Arc<T>`.
-    pub fn is_arc(&self) -> bool {
-        self.flags.contains(AdtFlags::IS_ARC)
-    }
-
-    /// Returns `true` if this is `Rc<T>`.
-    pub fn is_rc(&self) -> bool {
-        self.flags.contains(AdtFlags::IS_RC)
-    }
-
     /// Returns `true` if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 392abf37ba5..081e6f06b33 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -1864,24 +1864,6 @@ impl<'tcx> TyS<'tcx> {
         self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
     }
 
-    /// Returns `true` if this type is an `Arc<T>`.
-    #[inline]
-    pub fn is_arc(&self) -> bool {
-        match self.kind {
-            Adt(def, _) => def.is_arc(),
-            _ => false,
-        }
-    }
-
-    /// Returns `true` if this type is an `Rc<T>`.
-    #[inline]
-    pub fn is_rc(&self) -> bool {
-        match self.kind {
-            Adt(def, _) => def.is_rc(),
-            _ => false,
-        }
-    }
-
     #[inline]
     pub fn is_box(&self) -> bool {
         match self.kind {
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index 619ae0ff8fa..404cc0c7467 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{symbol::sym, Span};
 use rustc_target::abi::VariantIdx;
 
 use super::borrow_set::BorrowData;
@@ -632,20 +632,20 @@ pub(super) enum BorrowedContentSource<'tcx> {
 }
 
 impl BorrowedContentSource<'tcx> {
-    pub(super) fn describe_for_unnamed_place(&self) -> String {
+    pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
         match *self {
             BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
             BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(),
             BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
-            BorrowedContentSource::OverloadedDeref(ty) => {
-                if ty.is_rc() {
+            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind {
+                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
                     "an `Rc`".to_string()
-                } else if ty.is_arc() {
+                }
+                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
                     "an `Arc`".to_string()
-                } else {
-                    format!("dereference of `{}`", ty)
                 }
-            }
+                _ => format!("dereference of `{}`", ty),
+            },
             BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
         }
     }
@@ -662,22 +662,22 @@ impl BorrowedContentSource<'tcx> {
         }
     }
 
-    pub(super) fn describe_for_immutable_place(&self) -> String {
+    pub(super) fn describe_for_immutable_place(&self, tcx: TyCtxt<'_>) -> String {
         match *self {
             BorrowedContentSource::DerefRawPointer => "a `*const` pointer".to_string(),
             BorrowedContentSource::DerefSharedRef => "a `&` reference".to_string(),
             BorrowedContentSource::DerefMutableRef => {
                 bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
             }
-            BorrowedContentSource::OverloadedDeref(ty) => {
-                if ty.is_rc() {
+            BorrowedContentSource::OverloadedDeref(ty) => match ty.kind {
+                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
                     "an `Rc`".to_string()
-                } else if ty.is_arc() {
+                }
+                ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
                     "an `Arc`".to_string()
-                } else {
-                    format!("a dereference of `{}`", ty)
                 }
-            }
+                _ => format!("a dereference of `{}`", ty),
+            },
             BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
         }
     }
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index d32533b6ce9..1fbecb75dff 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -377,7 +377,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         span,
                         &format!("`{}` which is behind a {}", place_desc, source_desc),
                     ),
-                    (_, _) => self.cannot_move_out_of(span, &source.describe_for_unnamed_place()),
+                    (_, _) => self.cannot_move_out_of(
+                        span,
+                        &source.describe_for_unnamed_place(self.infcx.tcx),
+                    ),
                 }
             }
         };
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 35edd3d803d..635c299cf81 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -120,7 +120,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         local: the_place_err.local,
                         projection: proj_base,
                     });
-                    let pointer_type = source.describe_for_immutable_place();
+                    let pointer_type = source.describe_for_immutable_place(self.infcx.tcx);
                     opt_source = Some(source);
                     if let Some(desc) = access_place_desc {
                         item_msg = format!("`{}`", desc);
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 4e2423bc3b1..aaf30c583e2 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1019,7 +1019,9 @@ pub fn get_cmd_lint_options(
     for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
         for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
             let arg_pos = if let lint::Forbid = level {
-                // forbid is always specified last, so it can't be overridden
+                // HACK: forbid is always specified last, so it can't be overridden.
+                // FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
+                // fixed and `forbid` works as expected.
                 usize::max_value()
             } else {
                 passed_arg_pos
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 54b404e1161..6845cb3b9a3 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -144,6 +144,7 @@ symbols! {
         any,
         arbitrary_enum_discriminant,
         arbitrary_self_types,
+        Arc,
         Arguments,
         ArgumentV1,
         arm_target_feature,
@@ -582,6 +583,7 @@ symbols! {
         raw_dylib,
         raw_identifiers,
         raw_ref_op,
+        Rc,
         Ready,
         reason,
         recursion_limit,
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 9c57ffaf055..57e2349bb2e 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -902,8 +902,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: MethodError<'tcx>,
     ) {
         let rcvr = &args[0];
-        let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, rcvr_t, lang_item| {
-            if let Some(new_rcvr_t) = self.tcx.mk_lang_item(rcvr_t, lang_item) {
+        let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
+            if let Some(new_rcvr_t) = new_rcvr_t {
                 if let Ok(pick) = self.lookup_probe(
                     span,
                     segment.ident,
@@ -931,10 +931,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Try alternative arbitrary self types that could fulfill this call.
                 // FIXME: probe for all types that *could* be arbitrary self-types, not
                 // just this whitelist.
-                try_alt_rcvr(&mut err, rcvr_t, lang_items::OwnedBoxLangItem);
-                try_alt_rcvr(&mut err, rcvr_t, lang_items::PinTypeLangItem);
-                try_alt_rcvr(&mut err, rcvr_t, lang_items::Arc);
-                try_alt_rcvr(&mut err, rcvr_t, lang_items::Rc);
+                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::OwnedBoxLangItem));
+                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::PinTypeLangItem));
+                try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
+                try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
             }
             err.emit();
         }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index add706b5fcc..f075d1e74d4 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -271,11 +271,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
                         self.associated_item(info.def_id, item_name, Namespace::ValueNS)
                     });
-                    if let (true, false, SelfSource::MethodCall(expr), Some(_)) = (
+                    // There are methods that are defined on the primitive types and won't be
+                    // found when exploring `all_traits`, but we also need them to be acurate on
+                    // our suggestions (#47759).
+                    let fund_assoc = |opt_def_id: Option<DefId>| {
+                        opt_def_id
+                            .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
+                            .is_some()
+                    };
+                    let lang_items = tcx.lang_items();
+                    let found_candidate = candidates.next().is_some()
+                        || fund_assoc(lang_items.i8_impl())
+                        || fund_assoc(lang_items.i16_impl())
+                        || fund_assoc(lang_items.i32_impl())
+                        || fund_assoc(lang_items.i64_impl())
+                        || fund_assoc(lang_items.i128_impl())
+                        || fund_assoc(lang_items.u8_impl())
+                        || fund_assoc(lang_items.u16_impl())
+                        || fund_assoc(lang_items.u32_impl())
+                        || fund_assoc(lang_items.u64_impl())
+                        || fund_assoc(lang_items.u128_impl())
+                        || fund_assoc(lang_items.f32_impl())
+                        || fund_assoc(lang_items.f32_runtime_impl())
+                        || fund_assoc(lang_items.f64_impl())
+                        || fund_assoc(lang_items.f64_runtime_impl());
+                    if let (true, false, SelfSource::MethodCall(expr), true) = (
                         actual.is_numeric(),
                         actual.has_concrete_skeleton(),
                         source,
-                        candidates.next(),
+                        found_candidate,
                     ) {
                         let mut err = struct_span_err!(
                             tcx.sess,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index eebc34d3db8..a5490696ba0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1161,7 +1161,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
     fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
-                // infer the variable's type
+                // Infer the variable's type.
                 let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
                     kind: TypeVariableOriginKind::TypeInference,
                     span,
@@ -1173,7 +1173,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
                 var_ty
             }
             Some(typ) => {
-                // take type that the user specified
+                // Take type that the user specified.
                 self.fcx.locals.borrow_mut().insert(nid, typ);
                 typ.revealed_ty
             }
@@ -1244,7 +1244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
         intravisit::walk_pat(self, p);
     }
 
-    // Don't descend into the bodies of nested closures
+    // Don't descend into the bodies of nested closures.
     fn visit_fn(
         &mut self,
         _: intravisit::FnKind<'tcx>,
@@ -1292,7 +1292,7 @@ fn check_fn<'a, 'tcx>(
 
     debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
 
-    // Create the function context.  This is either derived from scratch or,
+    // 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.hir_id);
     *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index b3cace8298a..0335aba9144 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1353,23 +1353,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         def_bm: BindingMode,
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
-        let err = self.tcx.types.err;
         let expected = self.structurally_resolved_type(span, expected);
-        let (element_ty, slice_ty, inferred) = match expected.kind {
+        let (element_ty, opt_slice_ty, inferred) = match expected.kind {
             // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
             ty::Array(element_ty, len) => {
                 let min = before.len() as u64 + after.len() as u64;
-                let (slice_ty, expected) =
+                let (opt_slice_ty, expected) =
                     self.check_array_pat_len(span, element_ty, expected, slice, len, min);
-                (element_ty, slice_ty, expected)
+                // `opt_slice_ty.is_none()` => `slice.is_none()`.
+                // Note, though, that opt_slice_ty could be `Some(error_ty)`.
+                assert!(opt_slice_ty.is_some() || slice.is_none());
+                (element_ty, opt_slice_ty, expected)
             }
-            ty::Slice(element_ty) => (element_ty, expected, expected),
+            ty::Slice(element_ty) => (element_ty, Some(expected), expected),
             // The expected type must be an array or slice, but was neither, so error.
             _ => {
                 if !expected.references_error() {
                     self.error_expected_array_or_slice(span, expected);
                 }
-                (err, err, err)
+                let err = self.tcx.types.err;
+                (err, Some(err), err)
             }
         };
 
@@ -1379,7 +1382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         // Type check the `slice`, if present, against its expected type.
         if let Some(slice) = slice {
-            self.check_pat(&slice, slice_ty, def_bm, ti);
+            self.check_pat(&slice, opt_slice_ty.unwrap(), def_bm, ti);
         }
         // Type check the elements after `slice`, if present.
         for elt in after {
@@ -1390,9 +1393,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Type check the length of an array pattern.
     ///
-    /// Returns both the type of the variable length pattern
-    /// (or `tcx.err` in case there is none),
-    /// and the potentially inferred array type.
+    /// Returns both the type of the variable length pattern (or `None`), and the potentially
+    /// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
     fn check_array_pat_len(
         &self,
         span: Span,
@@ -1401,20 +1403,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         slice: Option<&'tcx Pat<'tcx>>,
         len: &ty::Const<'tcx>,
         min_len: u64,
-    ) -> (Ty<'tcx>, Ty<'tcx>) {
+    ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
         if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
             // Now we know the length...
             if slice.is_none() {
                 // ...and since there is no variable-length pattern,
                 // we require an exact match between the number of elements
                 // in the array pattern and as provided by the matched type.
-                if min_len != len {
-                    self.error_scrutinee_inconsistent_length(span, min_len, len);
+                if min_len == len {
+                    return (None, arr_ty);
                 }
+
+                self.error_scrutinee_inconsistent_length(span, min_len, len);
             } else if let Some(pat_len) = len.checked_sub(min_len) {
                 // The variable-length pattern was there,
                 // so it has an array type with the remaining elements left as its size...
-                return (self.tcx.mk_array(element_ty, pat_len), arr_ty);
+                return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty);
             } else {
                 // ...however, in this case, there were no remaining elements.
                 // That is, the slice pattern requires more than the array type offers.
@@ -1425,14 +1429,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // which we can use to infer the length of the array.
             let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
             self.demand_eqtype(span, updated_arr_ty, arr_ty);
-            return (self.tcx.types.err, updated_arr_ty);
+            return (None, updated_arr_ty);
         } else {
             // We have a variable-length pattern and don't know the array length.
             // This happens if we have e.g.,
             // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
             self.error_scrutinee_unfixed_length(span);
         }
-        (self.tcx.types.err, arr_ty)
+
+        // If we get here, we must have emitted an error.
+        (Some(self.tcx.types.err), arr_ty)
     }
 
     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 28574c68e94..146fc04bc27 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -40,7 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let item_def_id = self.tcx.hir().local_def_id(item_id);
 
         // This attribute causes us to dump some writeback information
-        // in the form of errors, which is uSymbolfor unit tests.
+        // in the form of errors, which is uSymbol for unit tests.
         let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
 
         let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);
diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs
index dcaf9208835..94467b9bdde 100644
--- a/src/test/ui/error-codes/E0152.rs
+++ b/src/test/ui/error-codes/E0152.rs
@@ -1,6 +1,6 @@
 #![feature(lang_items)]
 
-#[lang = "arc"]
+#[lang = "owned_box"]
 struct Foo; //~ ERROR E0152
 
 fn main() {
diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr
index 29981991ee0..fbaa276ce10 100644
--- a/src/test/ui/error-codes/E0152.stderr
+++ b/src/test/ui/error-codes/E0152.stderr
@@ -1,4 +1,4 @@
-error[E0152]: found duplicate lang item `arc`
+error[E0152]: found duplicate lang item `owned_box`
   --> $DIR/E0152.rs:4:1
    |
 LL | struct Foo;
diff --git a/src/test/ui/error-codes/E0718.rs b/src/test/ui/error-codes/E0718.rs
index 82ab2d4af1b..909cae0ba25 100644
--- a/src/test/ui/error-codes/E0718.rs
+++ b/src/test/ui/error-codes/E0718.rs
@@ -1,7 +1,7 @@
 #![feature(lang_items)]
 
-// Arc is expected to be a struct, so this will error.
-#[lang = "arc"] //~ ERROR language item must be applied to a struct
+// Box is expected to be a struct, so this will error.
+#[lang = "owned_box"] //~ ERROR language item must be applied to a struct
 static X: u32 = 42;
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0718.stderr b/src/test/ui/error-codes/E0718.stderr
index 412c856ce06..30378dd1674 100644
--- a/src/test/ui/error-codes/E0718.stderr
+++ b/src/test/ui/error-codes/E0718.stderr
@@ -1,8 +1,8 @@
-error[E0718]: `arc` language item must be applied to a struct
+error[E0718]: `owned_box` language item must be applied to a struct
   --> $DIR/E0718.rs:4:1
    |
-LL | #[lang = "arc"]
-   | ^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
+LL | #[lang = "owned_box"]
+   | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29181.rs b/src/test/ui/issues/issue-29181.rs
index 45752ad4f62..70e5bc01920 100644
--- a/src/test/ui/issues/issue-29181.rs
+++ b/src/test/ui/issues/issue-29181.rs
@@ -4,4 +4,6 @@ extern crate issue_29181 as foo;
 
 fn main() {
     0.homura(); //~ ERROR no method named `homura` found
+    // Issue #47759, detect existing method on the fundamental impl:
+    let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type
 }
diff --git a/src/test/ui/issues/issue-29181.stderr b/src/test/ui/issues/issue-29181.stderr
index 250b158ab8e..b66dcb88d00 100644
--- a/src/test/ui/issues/issue-29181.stderr
+++ b/src/test/ui/issues/issue-29181.stderr
@@ -4,6 +4,18 @@ error[E0599]: no method named `homura` found for type `{integer}` in the current
 LL |     0.homura();
    |       ^^^^^^ method not found in `{integer}`
 
-error: aborting due to previous error
+error[E0689]: can't call method `exp` on ambiguous numeric type `{float}`
+  --> $DIR/issue-29181.rs:8:30
+   |
+LL |     let _ = |x: f64| x * 2.0.exp();
+   |                              ^^^
+   |
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |     let _ = |x: f64| x * 2.0_f32.exp();
+   |                          ^^^^^^^
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0689.
+For more information about an error, try `rustc --explain E0599`.