about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-25 16:22:57 +0000
committerbors <bors@rust-lang.org>2021-08-25 16:22:57 +0000
commit7b0e554ee2c94e9b3865a8c2d24d720224512dec (patch)
treec593474b55894db3cd17a5a78200005ba265bd53
parenta992a11913b39a258158646bb1e03528c5aa5060 (diff)
parentd9ed23a9130b0941fd1ed4a651cbbec8a6621dd8 (diff)
downloadrust-7b0e554ee2c94e9b3865a8c2d24d720224512dec.tar.gz
rust-7b0e554ee2c94e9b3865a8c2d24d720224512dec.zip
Auto merge of #88329 - LeSeulArtichaut:rollup-blg8hc0, r=LeSeulArtichaut
Rollup of 16 pull requests

Successful merges:

 - #87944 (add Cell::as_array_of_cells, similar to Cell::as_slice_of_cells)
 - #88156 (Adjust / fix documentation of `Arc::make_mut`)
 - #88157 (bootstrap.py: recognize riscv64 when auto-detect)
 - #88196 (Refactor `named_asm_labels` to a HIR lint)
 - #88218 (Remove `Session.trait_methods_not_found`)
 - #88223 (Remove the `TryV2` alias)
 - #88226 (Fix typo “a Rc” → “an Rc” (and a few more))
 - #88267 (2229: Update signature for truncate function)
 - #88273 (Fix references to `ControlFlow` in docs)
 - #88277 (Update books)
 - #88291 (Add SAFETY comments to core::slice::sort::partition_in_blocks)
 - #88293 (Fix grammar in alloc test)
 - #88298 (Errorkind reorder)
 - #88299 (Stabilise BufWriter::into_parts)
 - #88314 (Add type of a let tait test)
 - #88325 (Add mutable-noalias to the release notes for 1.54)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast/src/visit.rs6
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs90
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/mod.rs10
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs124
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs33
-rw-r--r--compiler/rustc_session/src/session.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs23
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs5
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs118
-rw-r--r--library/alloc/src/rc.rs22
-rw-r--r--library/alloc/src/sync.rs38
-rw-r--r--library/alloc/tests/boxed.rs8
-rw-r--r--library/core/src/cell.rs20
-rw-r--r--library/core/src/iter/traits/iterator.rs12
-rw-r--r--library/core/src/ops/control_flow.rs4
-rw-r--r--library/core/src/ops/mod.rs8
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/result.rs2
-rw-r--r--library/core/src/slice/sort.rs26
-rw-r--r--library/core/src/task/poll.rs4
-rw-r--r--library/std/src/ffi/c_str.rs2
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/io/buffered/bufwriter.rs14
-rw-r--r--library/std/src/io/buffered/mod.rs2
-rw-r--r--library/std/src/io/error.rs52
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--src/bootstrap/bootstrap.py1
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/test/ui/asm/named-asm-labels.rs66
-rw-r--r--src/test/ui/asm/named-asm-labels.stderr125
-rw-r--r--src/test/ui/drop/dropck_legal_cycles.rs2
-rw-r--r--src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let.rs29
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let.stderr67
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let2.rs25
-rw-r--r--src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr21
45 files changed, 678 insertions, 315 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 2e7077ed206..dd299ca936a 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -175,6 +175,7 @@ Compiler
 - [Improved debugger output for enums on Windows MSVC platforms.][85292]
 - [Added tier 3\* support for `bpfel-unknown-none`
    and `bpfeb-unknown-none`.][79608]
+- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above.
 
 \* Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
@@ -244,6 +245,7 @@ Compatibility Notes
 [83366]: https://github.com/rust-lang/rust/pull/83366
 [83278]: https://github.com/rust-lang/rust/pull/83278
 [85292]: https://github.com/rust-lang/rust/pull/85292
+[82834]: https://github.com/rust-lang/rust/pull/82834
 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520
 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499
 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 575a00cdd0e..2c2d30d872e 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2028,6 +2028,7 @@ pub enum InlineAsmOperand {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct InlineAsm {
     pub template: Vec<InlineAsmTemplatePiece>,
+    pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
     pub clobber_abi: Option<(Symbol, Span)>,
     pub options: InlineAsmOptions,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a377763983a..774d5cb2dda 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -19,20 +19,20 @@ use crate::token;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AssocCtxt {
     Trait,
     Impl,
 }
 
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum FnCtxt {
     Free,
     Foreign,
     Assoc(AssocCtxt),
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
     Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index d94fb48d7cb..b9b27855a0b 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -392,8 +392,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let operands = self.arena.alloc_from_iter(operands);
         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
+        let template_strs = self.arena.alloc_from_iter(asm.template_strs.iter().cloned());
         let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
-        let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
+        let hir_asm =
+            hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
         self.arena.alloc(hir_asm)
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index cb0cfdcefdc..652165fb9b6 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -7,10 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
 use rustc_parse::parser::Parser;
 use rustc_parse_format as parse;
-use rustc_session::lint::{self, BuiltinLintDiagnostics};
+use rustc_session::lint;
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{InnerSpan, MultiSpan, Span};
+use rustc_span::{InnerSpan, Span};
 use rustc_target::asm::InlineAsmArch;
 use smallvec::smallvec;
 
@@ -484,11 +484,7 @@ fn parse_reg<'a>(
     Ok(result)
 }
 
-fn expand_preparsed_asm(
-    ecx: &mut ExtCtxt<'_>,
-    args: AsmArgs,
-    is_local_asm: bool,
-) -> Option<ast::InlineAsm> {
+fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::InlineAsm> {
     let mut template = vec![];
     // Register operands are implicitly used since they are not allowed to be
     // referenced in the template string.
@@ -501,6 +497,8 @@ fn expand_preparsed_asm(
     let mut line_spans = Vec::with_capacity(args.templates.len());
     let mut curarg = 0;
 
+    let mut template_strs = Vec::with_capacity(args.templates.len());
+
     for template_expr in args.templates.into_iter() {
         if !template.is_empty() {
             template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
@@ -524,8 +522,13 @@ fn expand_preparsed_asm(
             ast::StrStyle::Raw(raw) => Some(raw as usize),
         };
 
-        let template_str = &template_str.as_str();
         let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
+        template_strs.push((
+            template_str,
+            template_snippet.as_ref().map(|s| Symbol::intern(s)),
+            template_sp,
+        ));
+        let template_str = &template_str.as_str();
 
         if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
             let find_span = |needle: &str| -> Span {
@@ -560,72 +563,6 @@ fn expand_preparsed_asm(
             }
         }
 
-        // Lint against the use of named labels in inline `asm!` but not `global_asm!`
-        if is_local_asm {
-            let find_label_span = |needle: &str| -> Option<Span> {
-                if let Some(snippet) = &template_snippet {
-                    if let Some(pos) = snippet.find(needle) {
-                        let end = pos
-                            + &snippet[pos..]
-                                .find(|c| c == ':')
-                                .unwrap_or(snippet[pos..].len() - 1);
-                        let inner = InnerSpan::new(pos, end);
-                        return Some(template_sp.from_inner(inner));
-                    }
-                }
-
-                None
-            };
-
-            let mut found_labels = Vec::new();
-
-            // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
-            let statements = template_str.split(|c| matches!(c, '\n' | ';'));
-            for statement in statements {
-                // If there's a comment, trim it from the statement
-                let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
-                let mut start_idx = 0;
-                for (idx, _) in statement.match_indices(':') {
-                    let possible_label = statement[start_idx..idx].trim();
-                    let mut chars = possible_label.chars();
-                    if let Some(c) = chars.next() {
-                        // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
-                        if (c.is_alphabetic() || matches!(c, '.' | '_'))
-                            && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
-                        {
-                            found_labels.push(possible_label);
-                        } else {
-                            // If we encounter a non-label, there cannot be any further labels, so stop checking
-                            break;
-                        }
-                    } else {
-                        // Empty string means a leading ':' in this section, which is not a label
-                        break;
-                    }
-
-                    start_idx = idx + 1;
-                }
-            }
-
-            if found_labels.len() > 0 {
-                let spans =
-                    found_labels.into_iter().filter_map(find_label_span).collect::<Vec<Span>>();
-                // If there were labels but we couldn't find a span, combine the warnings and use the template span
-                let target_spans: MultiSpan =
-                    if spans.len() > 0 { spans.into() } else { template_sp.into() };
-                ecx.parse_sess().buffer_lint_with_diagnostic(
-                    lint::builtin::NAMED_ASM_LABELS,
-                    target_spans,
-                    ecx.current_expansion.lint_node_id,
-                    "avoid using named labels in inline assembly",
-                    BuiltinLintDiagnostics::NamedAsmLabel(
-                        "only local labels of the form `<number>:` should be used in inline asm"
-                            .to_string(),
-                    ),
-                );
-            }
-        }
-
         // Don't treat raw asm as a format string.
         if args.options.contains(ast::InlineAsmOptions::RAW) {
             template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
@@ -819,6 +756,7 @@ fn expand_preparsed_asm(
 
     Some(ast::InlineAsm {
         template,
+        template_strs: template_strs.into_boxed_slice(),
         operands: args.operands,
         clobber_abi: args.clobber_abi,
         options: args.options,
@@ -833,7 +771,7 @@ pub fn expand_asm<'cx>(
 ) -> Box<dyn base::MacResult + 'cx> {
     match parse_args(ecx, sp, tts, false) {
         Ok(args) => {
-            let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args, true) {
+            let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 P(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ExprKind::InlineAsm(P(inline_asm)),
@@ -860,7 +798,7 @@ pub fn expand_global_asm<'cx>(
 ) -> Box<dyn base::MacResult + 'cx> {
     match parse_args(ecx, sp, tts, true) {
         Ok(args) => {
-            if let Some(inline_asm) = expand_preparsed_asm(ecx, args, false) {
+            if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 MacEager::items(smallvec![P(ast::Item {
                     ident: Ident::invalid(),
                     attrs: Vec::new(),
diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs
index 5b27a407ad4..e7397bf13ba 100644
--- a/compiler/rustc_data_structures/src/owning_ref/mod.rs
+++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs
@@ -5,7 +5,7 @@
 
 This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut`
 that enables it to bundle a reference together with the owner of the data it points to.
-This allows moving and dropping of a `OwningRef` without needing to recreate the reference.
+This allows moving and dropping of an `OwningRef` without needing to recreate the reference.
 
 This can sometimes be useful because Rust borrowing rules normally prevent
 moving a type that has been moved from. For example, this kind of code gets rejected:
@@ -1146,7 +1146,7 @@ pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
 /// Typedef of an owning reference that uses a `String` as the owner.
 pub type StringRef = OwningRef<String, str>;
 
-/// Typedef of an owning reference that uses a `Rc` as the owner.
+/// Typedef of an owning reference that uses an `Rc` as the owner.
 pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
 /// Typedef of an owning reference that uses an `Arc` as the owner.
 pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
@@ -1157,9 +1157,9 @@ pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
 pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
 /// Typedef of an owning reference that uses a `MutexGuard` as the owner.
 pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
+/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner.
 pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
+/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner.
 pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
 
 /// Typedef of a mutable owning reference that uses a `Box` as the owner.
@@ -1173,7 +1173,7 @@ pub type StringRefMut = OwningRefMut<String, str>;
 pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
 /// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner.
 pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner.
+/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner.
 pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
 
 unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 888d1c1832b..38deb8eaaae 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2386,6 +2386,7 @@ impl<'hir> InlineAsmOperand<'hir> {
 #[derive(Debug, HashStable_Generic)]
 pub struct InlineAsm<'hir> {
     pub template: &'hir [InlineAsmTemplatePiece],
+    pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
     pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
     pub options: InlineAsmOptions,
     pub line_spans: &'hir [Span],
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 0ac4b6b25bb..d0bd508bc25 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -104,11 +104,5 @@ pub fn report_object_safety_error(
          to be resolvable dynamically; for more information visit \
          <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
     );
-
-    if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) {
-        // Avoid emitting error caused by non-existing method (#58734)
-        err.cancel();
-    }
-
     err
 }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index afa2cfca188..add0c0ff332 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -45,11 +45,11 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
-use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
 use rustc_target::abi::{LayoutOf, VariantIdx};
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
@@ -3140,3 +3140,123 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
         }
     }
 }
+
+declare_lint! {
+    /// The `named_asm_labels` lint detects the use of named labels in the
+    /// inline `asm!` macro.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(asm)]
+    /// fn main() {
+    ///     unsafe {
+    ///         asm!("foo: bar");
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// LLVM is allowed to duplicate inline assembly blocks for any
+    /// reason, for example when it is in a function that gets inlined. Because
+    /// of this, GNU assembler [local labels] *must* be used instead of labels
+    /// with a name. Using named labels might cause assembler or linker errors.
+    ///
+    /// See the [unstable book] for more details.
+    ///
+    /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
+    /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
+    pub NAMED_ASM_LABELS,
+    Deny,
+    "named labels in inline assembly",
+}
+
+declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]);
+
+impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        if let hir::Expr {
+            kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }),
+            ..
+        } = expr
+        {
+            for (template_sym, template_snippet, template_span) in template_strs.iter() {
+                let template_str = &template_sym.as_str();
+                let find_label_span = |needle: &str| -> Option<Span> {
+                    if let Some(template_snippet) = template_snippet {
+                        let snippet = template_snippet.as_str();
+                        if let Some(pos) = snippet.find(needle) {
+                            let end = pos
+                                + &snippet[pos..]
+                                    .find(|c| c == ':')
+                                    .unwrap_or(snippet[pos..].len() - 1);
+                            let inner = InnerSpan::new(pos, end);
+                            return Some(template_span.from_inner(inner));
+                        }
+                    }
+
+                    None
+                };
+
+                let mut found_labels = Vec::new();
+
+                // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
+                let statements = template_str.split(|c| matches!(c, '\n' | ';'));
+                for statement in statements {
+                    // If there's a comment, trim it from the statement
+                    let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
+                    let mut start_idx = 0;
+                    for (idx, _) in statement.match_indices(':') {
+                        let possible_label = statement[start_idx..idx].trim();
+                        let mut chars = possible_label.chars();
+                        if let Some(c) = chars.next() {
+                            // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
+                            if (c.is_alphabetic() || matches!(c, '.' | '_'))
+                                && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
+                            {
+                                found_labels.push(possible_label);
+                            } else {
+                                // If we encounter a non-label, there cannot be any further labels, so stop checking
+                                break;
+                            }
+                        } else {
+                            // Empty string means a leading ':' in this section, which is not a label
+                            break;
+                        }
+
+                        start_idx = idx + 1;
+                    }
+                }
+
+                debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels);
+
+                if found_labels.len() > 0 {
+                    let spans = found_labels
+                        .into_iter()
+                        .filter_map(|label| find_label_span(label))
+                        .collect::<Vec<Span>>();
+                    // If there were labels but we couldn't find a span, combine the warnings and use the template span
+                    let target_spans: MultiSpan =
+                        if spans.len() > 0 { spans.into() } else { (*template_span).into() };
+
+                    cx.lookup_with_diagnostics(
+                            NAMED_ASM_LABELS,
+                            Some(target_spans),
+                            |diag| {
+                                let mut err =
+                                    diag.build("avoid using named labels in inline assembly");
+                                err.emit();
+                            },
+                            BuiltinLintDiagnostics::NamedAsmLabel(
+                                "only local labels of the form `<number>:` should be used in inline asm"
+                                    .to_string(),
+                            ),
+                        );
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c4008e77bab..24ac723f2c9 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -168,6 +168,7 @@ macro_rules! late_lint_passes {
                 NonPanicFmt: NonPanicFmt,
                 NoopMethodCall: NoopMethodCall,
                 InvalidAtomicOrdering: InvalidAtomicOrdering,
+                NamedAsmLabels: NamedAsmLabels,
             ]
         );
     };
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index a1c507b4c84..1d978b6c829 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2469,38 +2469,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `named_asm_labels` lint detects the use of named labels in the
-    /// inline `asm!` macro.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// fn main() {
-    ///     unsafe {
-    ///         asm!("foo: bar");
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// LLVM is allowed to duplicate inline assembly blocks for any
-    /// reason, for example when it is in a function that gets inlined. Because
-    /// of this, GNU assembler [local labels] *must* be used instead of labels
-    /// with a name. Using named labels might cause assembler or linker errors.
-    ///
-    /// See the [unstable book] for more details.
-    ///
-    /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
-    /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
-    pub NAMED_ASM_LABELS,
-    Deny,
-    "named labels in inline assembly",
-}
-
-declare_lint! {
     /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
     /// functions without an explicit unsafe block.
     ///
@@ -3020,7 +2988,6 @@ declare_lint_pass! {
         INLINE_NO_SANITIZE,
         BAD_ASM_STYLE,
         ASM_SUB_REGISTER,
-        NAMED_ASM_LABELS,
         UNSAFE_OP_IN_UNSAFE_FN,
         INCOMPLETE_INCLUDE,
         CENUM_IMPL_DROP_CAST,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index d49ba861785..20e94e32be6 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -189,9 +189,6 @@ pub struct Session {
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
-    /// `Span`s of trait methods that weren't found to avoid emitting object safety errors
-    pub trait_methods_not_found: Lock<FxHashSet<Span>>,
-
     /// Mapping from ident span to path span for paths that don't exist as written, but that
     /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
     pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
@@ -1326,7 +1323,6 @@ pub fn build_session(
         print_fuel,
         jobserver: jobserver::client(),
         driver_lint_caps,
-        trait_methods_not_found: Lock::new(Default::default()),
         confused_type_with_std_module: Lock::new(Default::default()),
         ctfe_backtrace,
         miri_unleashed_features: Lock::new(Default::default()),
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index f9b7bb8ea99..0cf30fecf73 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -858,13 +858,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     path.segments,
                 );
             }
-            QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
+            QPath::TypeRelative(ref qself, ref segment) => {
+                // Don't use `self.to_ty`, since this will register a WF obligation.
+                // If we're trying to call a non-existent method on a trait
+                // (e.g. `MyTrait::missing_method`), then resolution will
+                // give us a `QPath::TypeRelative` with a trait object as
+                // `qself`. In that case, we want to avoid registering a WF obligation
+                // for `dyn MyTrait`, since we don't actually need the trait
+                // to be object-safe.
+                // We manually call `register_wf_obligation` in the success path
+                // below.
+                (<dyn AstConv<'_>>::ast_ty_to_ty(self, qself), qself, segment)
+            }
             QPath::LangItem(..) => {
                 bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
             }
         };
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
             let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@@ -878,6 +890,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
                     _ => Err(ErrorReported),
                 };
+
+                // If we have a path like `MyTrait::missing_method`, then don't register
+                // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
+                // register a WF obligation so that we can detect any additional
+                // errors in the self type.
+                if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
+                    self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
+                }
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
@@ -895,6 +915,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if result.is_ok() {
             self.maybe_lint_bare_trait(qpath, hir_id);
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
         }
 
         // Write back the new resolution.
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 1d5a9e3e1f9..afe274a2a79 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -70,15 +70,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn report_method_error(
         &self,
-        span: Span,
+        mut span: Span,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
         args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> Option<DiagnosticBuilder<'_>> {
-        let orig_span = span;
-        let mut span = span;
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
             return None;
@@ -545,7 +543,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     } else {
                         err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
                     }
-                    self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
                 };
 
                 // If the method name is the name of a field with a function or closure type,
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index fc7f55e24b2..84dfdd4d434 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -489,7 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut root_var_min_capture_list =
             typeck_results.closure_min_captures.remove(&closure_def_id).unwrap_or_default();
 
-        for (place, capture_info) in capture_information.into_iter() {
+        for (mut place, capture_info) in capture_information.into_iter() {
             let var_hir_id = match place.base {
                 PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
                 base => bug!("Expected upvar, found={:?}", base),
@@ -530,14 +530,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                         // Truncate the descendant (already in min_captures) to be same as the ancestor to handle any
                         // possible change in capture mode.
-                        let (_, descendant_capture_kind) = truncate_place_to_len(
-                            possible_descendant.place,
-                            possible_descendant.info.capture_kind,
+                        truncate_place_to_len_and_update_capture_kind(
+                            &mut possible_descendant.place,
+                            &mut possible_descendant.info.capture_kind,
                             place.projections.len(),
                         );
 
-                        possible_descendant.info.capture_kind = descendant_capture_kind;
-
                         updated_capture_info =
                             determine_capture_info(updated_capture_info, possible_descendant.info);
 
@@ -561,14 +559,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                             // Truncate the descendant (current place) to be same as the ancestor to handle any
                             // possible change in capture mode.
-                            let (_, descendant_capture_kind) = truncate_place_to_len(
-                                place.clone(),
-                                updated_capture_info.capture_kind,
+                            truncate_place_to_len_and_update_capture_kind(
+                                &mut place,
+                                &mut updated_capture_info.capture_kind,
                                 possible_ancestor.place.projections.len(),
                             );
 
-                            updated_capture_info.capture_kind = descendant_capture_kind;
-
                             possible_ancestor.info = determine_capture_info(
                                 possible_ancestor.info,
                                 updated_capture_info,
@@ -1476,7 +1472,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     place: &Place<'tcx>,
-    curr_borrow_kind: ty::UpvarCapture<'tcx>,
+    mut curr_borrow_kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let pos = place.projections.iter().enumerate().position(|(i, p)| {
         let ty = place.ty_before_projection(i);
@@ -1508,13 +1504,13 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
         }
     });
 
-    let place = place.clone();
+    let mut place = place.clone();
 
     if let Some(pos) = pos {
-        truncate_place_to_len(place, curr_borrow_kind, pos)
-    } else {
-        (place, curr_borrow_kind)
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_borrow_kind, pos);
     }
+
+    (place, curr_borrow_kind)
 }
 
 /// Returns a Ty that applies the specified capture kind on the provided capture Ty
@@ -1841,31 +1837,28 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
 ///   them completely.
 /// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
 fn restrict_precision_for_unsafe(
-    place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    if place.projections.is_empty() {
-        // Nothing to do here
-        return (place, curr_mode);
-    }
-
     if place.base_ty.is_unsafe_ptr() {
-        return truncate_place_to_len(place, curr_mode, 0);
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
     }
 
     if place.base_ty.is_union() {
-        return truncate_place_to_len(place, curr_mode, 0);
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
     }
 
     for (i, proj) in place.projections.iter().enumerate() {
         if proj.ty.is_unsafe_ptr() {
             // Don't apply any projections on top of an unsafe ptr.
-            return truncate_place_to_len(place, curr_mode, i + 1);
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
+            break;
         }
 
         if proj.ty.is_union() {
             // Don't capture preicse fields of a union.
-            return truncate_place_to_len(place, curr_mode, i + 1);
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
+            break;
         }
     }
 
@@ -1880,7 +1873,7 @@ fn restrict_capture_precision<'tcx>(
     place: Place<'tcx>,
     curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    let (place, curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
+    let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
 
     if place.projections.is_empty() {
         // Nothing to do here
@@ -1891,7 +1884,8 @@ fn restrict_capture_precision<'tcx>(
         match proj.kind {
             ProjectionKind::Index => {
                 // Arrays are completely captured, so we drop Index projections
-                return truncate_place_to_len(place, curr_mode, i);
+                truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
+                return (place, curr_mode);
             }
             ProjectionKind::Deref => {}
             ProjectionKind::Field(..) => {} // ignore
@@ -1906,8 +1900,8 @@ fn restrict_capture_precision<'tcx>(
 /// (or if closure attempts to move data that it doesn’t own).
 /// Note: When taking ownership, only capture data found on the stack.
 fn adjust_for_move_closure<'tcx>(
-    place: Place<'tcx>,
-    kind: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
     let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
@@ -1917,52 +1911,38 @@ fn adjust_for_move_closure<'tcx>(
 
         // If there's any Deref and the data needs to be moved into the closure body,
         // or it's a Deref of a Box, truncate the path to the first deref
-        _ if first_deref.is_some() => {
-            let place = match first_deref {
-                Some(idx) => {
-                    let (place, _) = truncate_place_to_len(place, kind, idx);
-                    place
-                }
-                None => place,
-            };
+        _ => {
+            if let Some(idx) = first_deref {
+                truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
+            }
 
             // AMAN: I think we don't need the span inside the ByValue anymore
             //       we have more detailed span in CaptureInfo
             (place, ty::UpvarCapture::ByValue(None))
         }
-
-        _ => (place, ty::UpvarCapture::ByValue(None)),
     }
 }
 
 /// Adjust closure capture just that if taking ownership of data, only move data
 /// from enclosing stack frame.
 fn adjust_for_non_move_closure<'tcx>(
-    place: Place<'tcx>,
+    mut place: Place<'tcx>,
     mut kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let contains_deref =
         place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
     match kind {
-        ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
-            let place = match contains_deref {
-                Some(idx) => {
-                    let (place, new_kind) = truncate_place_to_len(place, kind, idx);
-
-                    kind = new_kind;
-                    place
-                }
-                // Because of the if guard on the match on `kind`, we should never get here.
-                None => unreachable!(),
-            };
-
-            (place, kind)
+        ty::UpvarCapture::ByValue(..) => {
+            if let Some(idx) = contains_deref {
+                truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
+            }
         }
 
-        ty::UpvarCapture::ByValue(..) => (place, kind),
-        ty::UpvarCapture::ByRef(..) => (place, kind),
+        ty::UpvarCapture::ByRef(..) => {}
     }
+
+    (place, kind)
 }
 
 fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
@@ -2157,15 +2137,13 @@ fn determine_capture_info(
 ///
 /// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place`
 /// contained `Deref` of `&mut`.
-fn truncate_place_to_len(
-    mut place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+fn truncate_place_to_len_and_update_capture_kind(
+    place: &mut Place<'tcx>,
+    curr_mode: &mut ty::UpvarCapture<'tcx>,
     len: usize,
-) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+) {
     let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut));
 
-    let mut capture_kind = curr_mode;
-
     // If the truncated part of the place contains `Deref` of a `&mut` then convert MutBorrow ->
     // UniqueImmBorrow
     // Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
@@ -2176,7 +2154,7 @@ fn truncate_place_to_len(
                 if place.projections[i].kind == ProjectionKind::Deref
                     && is_mut_ref(place.ty_before_projection(i))
                 {
-                    capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                    *curr_mode = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
                         kind: ty::BorrowKind::UniqueImmBorrow,
                         region,
                     });
@@ -2190,8 +2168,6 @@ fn truncate_place_to_len(
     }
 
     place.projections.truncate(len);
-
-    (place, capture_kind)
 }
 
 /// Determines the Ancestry relationship of Place A relative to Place B
@@ -2256,8 +2232,8 @@ fn determine_place_ancestry_relation(
 /// }
 /// ```
 fn truncate_capture_for_optimization<'tcx>(
-    place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
 
@@ -2269,10 +2245,12 @@ fn truncate_capture_for_optimization<'tcx>(
     match idx {
         // If that pointer is a shared reference, then we don't need those fields.
         Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => {
-            truncate_place_to_len(place, curr_mode, idx + 1)
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, idx + 1)
         }
-        None | Some(_) => (place, curr_mode),
+        None | Some(_) => {}
     }
+
+    (place, curr_mode)
 }
 
 /// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 0b3079fa59d..0814652a5d4 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1011,7 +1011,7 @@ impl<T: ?Sized> Rc<T> {
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
-    /// the inner value when there are other pointers.
+    /// the inner value when there are other `Rc` pointers.
     ///
     /// [make_mut]: Rc::make_mut
     /// [clone]: Clone::clone
@@ -1100,10 +1100,12 @@ impl<T: Clone> Rc<T> {
     /// [`clone`] the inner value to a new allocation to ensure unique ownership.  This is also
     /// referred to as clone-on-write.
     ///
-    /// If there are no other `Rc` pointers to this allocation, then [`Weak`]
-    /// pointers to this allocation will be disassociated.
+    /// However, if there are no other `Rc` pointers to this allocation, but some [`Weak`]
+    /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
+    /// be cloned.
     ///
-    /// See also [`get_mut`], which will fail rather than cloning.
+    /// See also [`get_mut`], which will fail rather than cloning the inner value
+    /// or diassociating [`Weak`] pointers.
     ///
     /// [`clone`]: Clone::clone
     /// [`get_mut`]: Rc::get_mut
@@ -1115,11 +1117,11 @@ impl<T: Clone> Rc<T> {
     ///
     /// let mut data = Rc::new(5);
     ///
-    /// *Rc::make_mut(&mut data) += 1;        // Won't clone anything
-    /// let mut other_data = Rc::clone(&data);    // Won't clone inner data
-    /// *Rc::make_mut(&mut data) += 1;        // Clones inner data
-    /// *Rc::make_mut(&mut data) += 1;        // Won't clone anything
-    /// *Rc::make_mut(&mut other_data) *= 2;  // Won't clone anything
+    /// *Rc::make_mut(&mut data) += 1;         // Won't clone anything
+    /// let mut other_data = Rc::clone(&data); // Won't clone inner data
+    /// *Rc::make_mut(&mut data) += 1;         // Clones inner data
+    /// *Rc::make_mut(&mut data) += 1;         // Won't clone anything
+    /// *Rc::make_mut(&mut other_data) *= 2;   // Won't clone anything
     ///
     /// // Now `data` and `other_data` point to different allocations.
     /// assert_eq!(*data, 8);
@@ -1743,7 +1745,7 @@ impl<T: ?Sized> fmt::Pointer for Rc<T> {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_for_ptrs", since = "1.6.0")]
 impl<T> From<T> for Rc<T> {
-    /// Converts a generic type `T` into a `Rc<T>`
+    /// Converts a generic type `T` into an `Rc<T>`
     ///
     /// The conversion allocates on the heap and moves `t`
     /// from the stack into it.
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 3183a6db410..a066e0b49e2 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1346,18 +1346,19 @@ impl<T: ?Sized> Receiver for Arc<T> {}
 impl<T: Clone> Arc<T> {
     /// Makes a mutable reference into the given `Arc`.
     ///
-    /// If there are other `Arc` or [`Weak`] pointers to the same allocation,
-    /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
-    /// to ensure unique ownership. This is also referred to as clone-on-write.
+    /// If there are other `Arc` pointers to the same allocation, then `make_mut` will
+    /// [`clone`] the inner value to a new allocation to ensure unique ownership.  This is also
+    /// referred to as clone-on-write.
     ///
-    /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates
-    /// any remaining `Weak` pointers.
+    /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`]
+    /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
+    /// be cloned.
     ///
-    /// See also [`get_mut`][get_mut], which will fail rather than cloning.
+    /// See also [`get_mut`], which will fail rather than cloning the inner value
+    /// or diassociating [`Weak`] pointers.
     ///
-    /// [clone]: Clone::clone
-    /// [get_mut]: Arc::get_mut
-    /// [`Rc::make_mut`]: super::rc::Rc::make_mut
+    /// [`clone`]: Clone::clone
+    /// [`get_mut`]: Arc::get_mut
     ///
     /// # Examples
     ///
@@ -1376,6 +1377,23 @@ impl<T: Clone> Arc<T> {
     /// assert_eq!(*data, 8);
     /// assert_eq!(*other_data, 12);
     /// ```
+    ///
+    /// [`Weak`] pointers will be disassociated:
+    ///
+    /// ```
+    /// use std::sync::Arc;
+    ///
+    /// let mut data = Arc::new(75);
+    /// let weak = Arc::downgrade(&data);
+    ///
+    /// assert!(75 == *data);
+    /// assert!(75 == *weak.upgrade().unwrap());
+    ///
+    /// *Arc::make_mut(&mut data) += 1;
+    ///
+    /// assert!(76 == *data);
+    /// assert!(weak.upgrade().is_none());
+    /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "arc_unique", since = "1.4.0")]
@@ -1441,7 +1459,7 @@ impl<T: ?Sized> Arc<T> {
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
-    /// the inner value when there are other pointers.
+    /// the inner value when there are other `Arc` pointers.
     ///
     /// [make_mut]: Arc::make_mut
     /// [clone]: Clone::clone
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 6a83f5da87c..a38b5c471bf 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -35,11 +35,11 @@ fn box_clone_and_clone_from_equivalence() {
     }
 }
 
-/// This test might give a false positive in case the box realocates, but the alocator keeps the
-/// original pointer.
+/// This test might give a false positive in case the box reallocates,
+/// but the allocator keeps the original pointer.
 ///
-/// On the other hand it won't give a false negative, if it fails than the memory was definitely not
-/// reused
+/// On the other hand, it won't give a false negative: If it fails, then the
+/// memory was definitely not reused.
 #[test]
 fn box_clone_from_ptr_stability() {
     for size in (0..8).map(|i| 2usize.pow(i)) {
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index f0c934edf39..85b43f48847 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -576,6 +576,26 @@ impl<T> Cell<[T]> {
     }
 }
 
+impl<T, const N: usize> Cell<[T; N]> {
+    /// Returns a `&[Cell<T>; N]` from a `&Cell<[T; N]>`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(as_array_of_cells)]
+    /// use std::cell::Cell;
+    ///
+    /// let mut array: [i32; 3] = [1, 2, 3];
+    /// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
+    /// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
+    /// ```
+    #[unstable(feature = "as_array_of_cells", issue = "88248")]
+    pub fn as_array_of_cells(&self) -> &[Cell<T>; N] {
+        // SAFETY: `Cell<T>` has the same memory layout as `T`.
+        unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }
+    }
+}
+
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](self) for more.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 524d8f857e2..850435b53cc 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1957,8 +1957,8 @@ pub trait Iterator {
     /// assert_eq!(it.next(), Some(&40));
     /// ```
     ///
-    /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`]
-    /// type allows a similar idea:
+    /// While you cannot `break` from a closure, the [`ControlFlow`] type allows
+    /// a similar idea:
     ///
     /// ```
     /// use std::ops::ControlFlow;
@@ -2024,8 +2024,8 @@ pub trait Iterator {
     /// assert_eq!(it.next(), Some("stale_bread.json"));
     /// ```
     ///
-    /// The [`crate::ops::ControlFlow`] type can be used with this method for the
-    /// situations in which you'd use `break` and `continue` in a normal loop:
+    /// The [`ControlFlow`] type can be used with this method for the situations
+    /// in which you'd use `break` and `continue` in a normal loop:
     ///
     /// ```
     /// use std::ops::ControlFlow;
@@ -2442,14 +2442,14 @@ pub trait Iterator {
         R: Try<Output = bool>,
         // FIXME: This bound is rather strange, but means minimal breakage on nightly.
         // See #85115 for the issue tracking a holistic solution for this and try_map.
-        R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+        R: Try<Residual = Result<crate::convert::Infallible, E>>,
     {
         #[inline]
         fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
         where
             F: FnMut(&T) -> R,
             R: Try<Output = bool>,
-            R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+            R: Try<Residual = Result<crate::convert::Infallible, E>>,
         {
             move |(), x| match f(&x).branch() {
                 ControlFlow::Continue(false) => ControlFlow::CONTINUE,
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index c2270c864df..cd2d57699c9 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -63,7 +63,7 @@ pub enum ControlFlow<B, C = ()> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::TryV2 for ControlFlow<B, C> {
+impl<B, C> ops::Try for ControlFlow<B, C> {
     type Output = C;
     type Residual = ControlFlow<B, convert::Infallible>;
 
@@ -165,7 +165,7 @@ impl<B, C> ControlFlow<B, C> {
 /// These are used only as part of implementing the iterator adapters.
 /// They have mediocre names and non-obvious semantics, so aren't
 /// currently on a path to potential stabilization.
-impl<R: ops::TryV2> ControlFlow<R, R::Output> {
+impl<R: ops::Try> ControlFlow<R, R::Output> {
     /// Create a `ControlFlow` from any type implementing `Try`.
     #[inline]
     pub(crate) fn from_try(r: R) -> Self {
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 85e04740d96..bd7feb8b183 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -182,13 +182,7 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-pub use self::try_trait::FromResidual;
-
-#[unstable(feature = "try_trait_v2", issue = "84277")]
-pub use self::try_trait::Try;
-
-#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
-pub(crate) use self::try_trait::Try as TryV2;
+pub use self::try_trait::{FromResidual, Try};
 
 #[unstable(feature = "generator_trait", issue = "43122")]
 pub use self::generator::{Generator, GeneratorState};
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 78f5954532f..47865240f6a 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -2013,7 +2013,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T> ops::TryV2 for Option<T> {
+impl<T> ops::Try for Option<T> {
     type Output = T;
     type Residual = Option<convert::Infallible>;
 
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 861790e8a40..092e6544342 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1889,7 +1889,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Result<T, E> {
+impl<T, E> ops::Try for Result<T, E> {
     type Output = T;
     type Residual = Result<convert::Infallible, E>;
 
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 36c2c4abdb4..8a31388fbdb 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -369,6 +369,22 @@ where
             // Instead of swapping one pair at the time, it is more efficient to perform a cyclic
             // permutation. This is not strictly equivalent to swapping, but produces a similar
             // result using fewer memory operations.
+
+            // SAFETY: The use of `ptr::read` is valid because there is at least one element in
+            // both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from.
+            //
+            // The uses of `left!` involve calls to `offset` on `l`, which points to the
+            // beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so
+            // these `offset` calls are safe as all reads are within the block. The same argument
+            // applies for the uses of `right!`.
+            //
+            // The calls to `start_l.offset` are valid because there are at most `count-1` of them,
+            // plus the final one at the end of the unsafe block, where `count` is the minimum number
+            // of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not
+            // being enough elements. The same reasoning applies to the calls to `start_r.offset`.
+            //
+            // The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed
+            // not to overlap, and are valid because of the reasoning above.
             unsafe {
                 let tmp = ptr::read(left!());
                 ptr::copy_nonoverlapping(right!(), left!(), 1);
@@ -389,11 +405,21 @@ where
 
         if start_l == end_l {
             // All out-of-order elements in the left block were moved. Move to the next block.
+
+            // block-width-guarantee
+            // SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There
+            // are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is
+            // safe. Otherwise, the debug assertions in the `is_done` case guarantee that
+            // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
+            // for the smaller number of remaining elements.
             l = unsafe { l.offset(block_l as isize) };
         }
 
         if start_r == end_r {
             // All out-of-order elements in the right block were moved. Move to the previous block.
+
+            // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
+            // or `block_r` has been adjusted for the last handful of elements.
             r = unsafe { r.offset(-(block_r as isize)) };
         }
 
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index fc0a4e74797..25070460996 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -222,7 +222,7 @@ impl<T> From<T> for Poll<T> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
+impl<T, E> ops::Try for Poll<Result<T, E>> {
     type Output = Poll<T>;
     type Residual = Result<convert::Infallible, E>;
 
@@ -252,7 +252,7 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
+impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
     type Output = Poll<Option<T>>;
     type Residual = Result<convert::Infallible, E>;
 
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 0d082648591..de05c377852 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -958,7 +958,7 @@ impl From<&CStr> for Arc<CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
-    /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
+    /// Converts a [`CString`] into an [`Rc`]`<CStr>` without copying or allocating.
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index f05295f89af..21f354caf6a 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -916,7 +916,7 @@ impl From<&OsStr> for Arc<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
-    /// Converts an [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
+    /// Converts an [`OsString`] into an [`Rc`]`<OsStr>` without copying or allocating.
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 9da5fbff9cf..df60af7c36a 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -323,7 +323,6 @@ impl<W: Write> BufWriter<W> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(bufwriter_into_parts)]
     /// use std::io::{BufWriter, Write};
     ///
     /// let mut buffer = [0u8; 10];
@@ -334,7 +333,7 @@ impl<W: Write> BufWriter<W> {
     /// assert_eq!(recovered_writer.len(), 0);
     /// assert_eq!(&buffered_data.unwrap(), b"ata");
     /// ```
-    #[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+    #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
     pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
         let buf = mem::take(&mut self.buf);
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
@@ -444,14 +443,13 @@ impl<W: Write> BufWriter<W> {
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 /// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying
 /// writer has previously panicked.  Contains the (possibly partly written) buffered data.
 ///
 /// # Example
 ///
 /// ```
-/// #![feature(bufwriter_into_parts)]
 /// use std::io::{self, BufWriter, Write};
 /// use std::panic::{catch_unwind, AssertUnwindSafe};
 ///
@@ -478,7 +476,7 @@ pub struct WriterPanicked {
 impl WriterPanicked {
     /// Returns the perhaps-unwritten data.  Some of this data may have been written by the
     /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea.
-    #[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+    #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
     pub fn into_inner(self) -> Vec<u8> {
         self.buf
     }
@@ -487,7 +485,7 @@ impl WriterPanicked {
         "BufWriter inner writer panicked, what data remains unwritten is not known";
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl error::Error for WriterPanicked {
     #[allow(deprecated, deprecated_in_future)]
     fn description(&self) -> &str {
@@ -495,14 +493,14 @@ impl error::Error for WriterPanicked {
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl fmt::Display for WriterPanicked {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", Self::DESCRIPTION)
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl fmt::Debug for WriterPanicked {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("WriterPanicked")
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
index 8cfffc2fd35..179bdf7fe55 100644
--- a/library/std/src/io/buffered/mod.rs
+++ b/library/std/src/io/buffered/mod.rs
@@ -14,7 +14,7 @@ use crate::io::Error;
 
 pub use bufreader::BufReader;
 pub use bufwriter::BufWriter;
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 pub use bufwriter::WriterPanicked;
 pub use linewriter::LineWriter;
 use linewritershim::LineWriterShim;
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 829ef3d98bb..51666c0a3c7 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -261,19 +261,15 @@ pub enum ErrorKind {
     #[stable(feature = "rust1", since = "1.0.0")]
     Interrupted,
 
-    /// A custom error that does not fall under any other I/O error kind.
-    ///
-    /// This can be used to construct your own [`Error`]s that do not match any
-    /// [`ErrorKind`].
-    ///
-    /// This [`ErrorKind`] is not used by the standard library.
+    /// This operation is unsupported on this platform.
     ///
-    /// Errors from the standard library that do not fall under any of the I/O
-    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
-    /// New [`ErrorKind`]s might be added in the future for some of those.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    Other,
+    /// This means that the operation can never succeed.
+    #[stable(feature = "unsupported_error", since = "1.53.0")]
+    Unsupported,
 
+    // ErrorKinds which are primarily categorisations for OS error
+    // codes should be added above.
+    //
     /// An error returned when an operation could not be completed because an
     /// "end of file" was reached prematurely.
     ///
@@ -283,17 +279,28 @@ pub enum ErrorKind {
     #[stable(feature = "read_exact", since = "1.6.0")]
     UnexpectedEof,
 
-    /// This operation is unsupported on this platform.
-    ///
-    /// This means that the operation can never succeed.
-    #[stable(feature = "unsupported_error", since = "1.53.0")]
-    Unsupported,
-
     /// An operation could not be completed, because it failed
     /// to allocate enough memory.
     #[stable(feature = "out_of_memory_error", since = "1.54.0")]
     OutOfMemory,
 
+    // "Unusual" error kinds which do not correspond simply to (sets
+    // of) OS error codes, should be added just above this comment.
+    // `Other` and `Uncategorised` should remain at the end:
+    //
+    /// A custom error that does not fall under any other I/O error kind.
+    ///
+    /// This can be used to construct your own [`Error`]s that do not match any
+    /// [`ErrorKind`].
+    ///
+    /// This [`ErrorKind`] is not used by the standard library.
+    ///
+    /// Errors from the standard library that do not fall under any of the I/O
+    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
+    /// New [`ErrorKind`]s might be added in the future for some of those.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    Other,
+
     /// Any I/O error from the standard library that's not part of this list.
     ///
     /// Errors that are `Uncategorized` now may move to a different or a new
@@ -307,13 +314,13 @@ pub enum ErrorKind {
 impl ErrorKind {
     pub(crate) fn as_str(&self) -> &'static str {
         use ErrorKind::*;
+        // Strictly alphabetical, please.  (Sadly rustfmt cannot do this yet.)
         match *self {
             AddrInUse => "address in use",
             AddrNotAvailable => "address not available",
             AlreadyExists => "entity already exists",
             ArgumentListTooLong => "argument list too long",
             BrokenPipe => "broken pipe",
-            ResourceBusy => "resource busy",
             ConnectionAborted => "connection aborted",
             ConnectionRefused => "connection refused",
             ConnectionReset => "connection reset",
@@ -321,9 +328,10 @@ impl ErrorKind {
             Deadlock => "deadlock",
             DirectoryNotEmpty => "directory not empty",
             ExecutableFileBusy => "executable file busy",
+            FileTooLarge => "file too large",
             FilenameTooLong => "filename too long",
+            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
             FilesystemQuotaExceeded => "filesystem quota exceeded",
-            FileTooLarge => "file too large",
             HostUnreachable => "host unreachable",
             Interrupted => "operation interrupted",
             InvalidData => "invalid data",
@@ -332,16 +340,16 @@ impl ErrorKind {
             NetworkDown => "network down",
             NetworkUnreachable => "network unreachable",
             NotADirectory => "not a directory",
-            StorageFull => "no storage space",
             NotConnected => "not connected",
             NotFound => "entity not found",
+            NotSeekable => "seek on unseekable file",
             Other => "other error",
             OutOfMemory => "out of memory",
             PermissionDenied => "permission denied",
             ReadOnlyFilesystem => "read-only filesystem or storage medium",
+            ResourceBusy => "resource busy",
             StaleNetworkFileHandle => "stale network file handle",
-            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
-            NotSeekable => "seek on unseekable file",
+            StorageFull => "no storage space",
             TimedOut => "timed out",
             TooManyLinks => "too many links",
             Uncategorized => "uncategorized error",
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 28254fea0d3..e8466fa06b8 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -264,7 +264,7 @@ use crate::sys_common::memchr;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::buffered::IntoInnerError;
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 pub use self::buffered::WriterPanicked;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::buffered::{BufReader, BufWriter, LineWriter};
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 3faf38c66ec..e34768bc2c9 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -301,6 +301,7 @@ def default_build_triple(verbose):
         'ppc': 'powerpc',
         'ppc64': 'powerpc64',
         'ppc64le': 'powerpc64le',
+        'riscv64': 'riscv64gc',
         's390x': 's390x',
         'x64': 'x86_64',
         'x86': 'i686',
diff --git a/src/doc/book b/src/doc/book
-Subproject 7e49659102f0977d9142190e1ba23345c0f00eb
+Subproject 687e21bde2ea10c261f79fa14797c5137425098
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 4884fe45c14f8b22121760fb117181bb4da8dfe
+Subproject da6ea9b03f74cae0a292f40315723d7a3a97363
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 0dc9cd4e89f00cb5230f120e1a083916386e422
+Subproject 04f489c889235fe3b6dfe678ae5410d07deda95
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35
+Subproject cf0e151b7925a40f13fbc6573c6f97d5f94c7c1
diff --git a/src/test/ui/asm/named-asm-labels.rs b/src/test/ui/asm/named-asm-labels.rs
index 803501b40b6..9f487bd8061 100644
--- a/src/test/ui/asm/named-asm-labels.rs
+++ b/src/test/ui/asm/named-asm-labels.rs
@@ -1,6 +1,14 @@
 // only-x86_64
 
-#![feature(asm, global_asm)]
+// Tests that the use of named labels in the `asm!` macro are linted against
+// except for in `#[naked]` fns.
+// Using a named label is incorrect as per the RFC because for most cases
+// the compiler cannot ensure that inline asm is emitted exactly once per
+// codegen unit (except for naked fns) and so the label could be duplicated
+// which causes less readable LLVM errors and in the worst cases causes ICEs
+// or segfaults based on system dependent behavior and codegen flags.
+
+#![feature(asm, global_asm, naked_functions)]
 
 #[no_mangle]
 pub static FOO: usize = 42;
@@ -126,5 +134,61 @@ fn main() {
     }
 }
 
+// Trigger on naked fns too, even though they can't be inlined, reusing a
+// label or LTO can cause labels to break
+#[naked]
+pub extern "C" fn foo() -> i32 {
+    unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+// Make sure that non-naked attributes *do* still let the lint happen
+#[no_mangle]
+pub extern "C" fn bar() {
+    unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+    //~^ ERROR avoid using named labels
+}
+
+#[naked]
+pub extern "C" fn aaa() {
+    fn _local() {}
+
+    unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+pub fn normal() {
+    fn _local1() {}
+
+    #[naked]
+    pub extern "C" fn bbb() {
+        fn _very_local() {}
+
+        unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+    }
+
+    fn _local2() {}
+}
+
+// Make sure that the lint happens within closures
+fn closures() {
+    || unsafe {
+        asm!("closure1: nop"); //~ ERROR avoid using named labels
+    };
+
+    move || unsafe {
+        asm!("closure2: nop"); //~ ERROR avoid using named labels
+    };
+
+    || {
+        #[naked]
+        unsafe extern "C" fn _nested() {
+            asm!("ret;", options(noreturn));
+        }
+
+        unsafe {
+            asm!("closure3: nop"); //~ ERROR avoid using named labels
+        }
+    };
+}
+
 // Don't trigger on global asm
 global_asm!("aaaaaaaa: nop");
diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr
index 3c4a4db75e0..396f0a19424 100644
--- a/src/test/ui/asm/named-asm-labels.stderr
+++ b/src/test/ui/asm/named-asm-labels.stderr
@@ -1,5 +1,5 @@
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:11:15
+  --> $DIR/named-asm-labels.rs:19:15
    |
 LL |         asm!("bar: nop");
    |               ^^^
@@ -9,7 +9,7 @@ LL |         asm!("bar: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:14:15
+  --> $DIR/named-asm-labels.rs:22:15
    |
 LL |         asm!("abcd:");
    |               ^^^^
@@ -18,7 +18,7 @@ LL |         asm!("abcd:");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:17:15
+  --> $DIR/named-asm-labels.rs:25:15
    |
 LL |         asm!("foo: bar1: nop");
    |               ^^^  ^^^^
@@ -27,7 +27,7 @@ LL |         asm!("foo: bar1: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:21:15
+  --> $DIR/named-asm-labels.rs:29:15
    |
 LL |         asm!("foo1: nop", "nop");
    |               ^^^^
@@ -36,7 +36,7 @@ LL |         asm!("foo1: nop", "nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:22:15
+  --> $DIR/named-asm-labels.rs:30:15
    |
 LL |         asm!("foo2: foo3: nop", "nop");
    |               ^^^^  ^^^^
@@ -45,7 +45,7 @@ LL |         asm!("foo2: foo3: nop", "nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:24:22
+  --> $DIR/named-asm-labels.rs:32:22
    |
 LL |         asm!("nop", "foo4: nop");
    |                      ^^^^
@@ -54,7 +54,7 @@ LL |         asm!("nop", "foo4: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:25:15
+  --> $DIR/named-asm-labels.rs:33:15
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |               ^^^^
@@ -63,7 +63,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:25:28
+  --> $DIR/named-asm-labels.rs:33:28
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |                            ^^^^
@@ -72,7 +72,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:30:15
+  --> $DIR/named-asm-labels.rs:38:15
    |
 LL |         asm!("foo7: nop; foo8: nop");
    |               ^^^^       ^^^^
@@ -81,7 +81,7 @@ LL |         asm!("foo7: nop; foo8: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:32:15
+  --> $DIR/named-asm-labels.rs:40:15
    |
 LL |         asm!("foo9: nop; nop");
    |               ^^^^
@@ -90,7 +90,7 @@ LL |         asm!("foo9: nop; nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:33:20
+  --> $DIR/named-asm-labels.rs:41:20
    |
 LL |         asm!("nop; foo10: nop");
    |                    ^^^^^
@@ -99,7 +99,7 @@ LL |         asm!("nop; foo10: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:36:15
+  --> $DIR/named-asm-labels.rs:44:15
    |
 LL |         asm!("bar2: nop\n bar3: nop");
    |               ^^^^        ^^^^
@@ -108,7 +108,7 @@ LL |         asm!("bar2: nop\n bar3: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:38:15
+  --> $DIR/named-asm-labels.rs:46:15
    |
 LL |         asm!("bar4: nop\n nop");
    |               ^^^^
@@ -117,7 +117,7 @@ LL |         asm!("bar4: nop\n nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:39:21
+  --> $DIR/named-asm-labels.rs:47:21
    |
 LL |         asm!("nop\n bar5: nop");
    |                     ^^^^
@@ -126,7 +126,7 @@ LL |         asm!("nop\n bar5: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:40:21
+  --> $DIR/named-asm-labels.rs:48:21
    |
 LL |         asm!("nop\n bar6: bar7: nop");
    |                     ^^^^  ^^^^
@@ -135,7 +135,7 @@ LL |         asm!("nop\n bar6: bar7: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:46:13
+  --> $DIR/named-asm-labels.rs:54:13
    |
 LL |             blah2: nop
    |             ^^^^^
@@ -146,7 +146,7 @@ LL |             blah3: nop
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:55:19
+  --> $DIR/named-asm-labels.rs:63:19
    |
 LL |             nop ; blah4: nop
    |                   ^^^^^
@@ -155,7 +155,7 @@ LL |             nop ; blah4: nop
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:69:15
+  --> $DIR/named-asm-labels.rs:77:15
    |
 LL |         asm!("blah1: 2bar: nop");
    |               ^^^^^
@@ -164,7 +164,7 @@ LL |         asm!("blah1: 2bar: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:72:15
+  --> $DIR/named-asm-labels.rs:80:15
    |
 LL |         asm!("def: def: nop");
    |               ^^^
@@ -173,7 +173,7 @@ LL |         asm!("def: def: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:73:15
+  --> $DIR/named-asm-labels.rs:81:15
    |
 LL |         asm!("def: nop\ndef: nop");
    |               ^^^
@@ -182,7 +182,7 @@ LL |         asm!("def: nop\ndef: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:74:15
+  --> $DIR/named-asm-labels.rs:82:15
    |
 LL |         asm!("def: nop; def: nop");
    |               ^^^
@@ -191,7 +191,7 @@ LL |         asm!("def: nop; def: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:82:15
+  --> $DIR/named-asm-labels.rs:90:15
    |
 LL |         asm!("fooo\u{003A} nop");
    |               ^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |         asm!("fooo\u{003A} nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:83:15
+  --> $DIR/named-asm-labels.rs:91:15
    |
 LL |         asm!("foooo\x3A nop");
    |               ^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |         asm!("foooo\x3A nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:86:15
+  --> $DIR/named-asm-labels.rs:94:15
    |
 LL |         asm!("fooooo:\u{000A} nop");
    |               ^^^^^^
@@ -218,7 +218,7 @@ LL |         asm!("fooooo:\u{000A} nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:87:15
+  --> $DIR/named-asm-labels.rs:95:15
    |
 LL |         asm!("foooooo:\x0A nop");
    |               ^^^^^^^
@@ -227,7 +227,7 @@ LL |         asm!("foooooo:\x0A nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:91:14
+  --> $DIR/named-asm-labels.rs:99:14
    |
 LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:102:13
+  --> $DIR/named-asm-labels.rs:110:13
    |
 LL |             ab: nop // ab: does foo
    |             ^^
@@ -245,7 +245,7 @@ LL |             ab: nop // ab: does foo
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:114:14
+  --> $DIR/named-asm-labels.rs:122:14
    |
 LL |         asm!(include_str!("named-asm-labels.s"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,18 +254,81 @@ LL |         asm!(include_str!("named-asm-labels.s"));
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 warning: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:124:19
+  --> $DIR/named-asm-labels.rs:132:19
    |
 LL |             asm!("warned: nop");
    |                   ^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/named-asm-labels.rs:122:16
+  --> $DIR/named-asm-labels.rs:130:16
    |
 LL |         #[warn(named_asm_labels)]
    |                ^^^^^^^^^^^^^^^^
    = help: only local labels of the form `<number>:` should be used in inline asm
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
-error: aborting due to 28 previous errors; 1 warning emitted
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:141:20
+   |
+LL |     unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:147:20
+   |
+LL |     unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:155:20
+   |
+LL |     unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:165:24
+   |
+LL |         unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
+   |                        ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:174:15
+   |
+LL |         asm!("closure1: nop");
+   |               ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:178:15
+   |
+LL |         asm!("closure2: nop");
+   |               ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:188:19
+   |
+LL |             asm!("closure3: nop");
+   |                   ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: aborting due to 35 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs
index fb13fd764bf..27a599315dc 100644
--- a/src/test/ui/drop/dropck_legal_cycles.rs
+++ b/src/test/ui/drop/dropck_legal_cycles.rs
@@ -368,7 +368,7 @@ pub fn main() {
     // We can use refcells if we're single-threaded (as this test is).
     // If one were to generalize these constructions to a
     // multi-threaded context, then it might seem like we could choose
-    // between either a RwLock or a Mutex to hold the owned arcs on
+    // between either an RwLock or a Mutex to hold the owned arcs on
     // each node.
     //
     // Part of the point of this test is to actually confirm that the
diff --git a/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs b/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs
index ea3ad7aed49..329fadb150f 100644
--- a/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs
+++ b/src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(as_array_of_cells)]
+
 use std::cell::Cell;
 
 fn main() {
@@ -8,4 +10,11 @@ fn main() {
     let slice_cell: &[Cell<i32>] = cell_slice.as_slice_of_cells();
 
     assert_eq!(slice_cell.len(), 3);
+
+    let mut array: [i32; 3] = [1, 2, 3];
+    let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
+    let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
+
+    array_cell[0].set(99);
+    assert_eq!(array, [99, 2, 3]);
 }
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
new file mode 100644
index 00000000000..7f8e6127cca
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -0,0 +1,29 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME This should compile, but it currently doesn't
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+//~^ ERROR: could not find defining uses
+
+fn foo1() -> u32 {
+    let x: Foo = 22_u32;
+    //~^ ERROR: mismatched types [E0308]
+    x
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn foo2() -> u32 {
+    let x: Foo = 22_u32;
+    //~^ ERROR: mismatched types [E0308]
+    let y: Foo = x;
+    same_type((x, y));
+    y
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn same_type<T>(x: (T, T)) {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
new file mode 100644
index 00000000000..cac8d6841af
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
@@ -0,0 +1,67 @@
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:12:18
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     let x: Foo = 22_u32;
+   |            ---   ^^^^^^ expected opaque type, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:14:5
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the found opaque type
+...
+LL | fn foo1() -> u32 {
+   |              --- expected `u32` because of return type
+...
+LL |     x
+   |     ^ expected `u32`, found opaque type
+   |
+   = note:     expected type `u32`
+           found opaque type `impl Debug`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:19:18
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     let x: Foo = 22_u32;
+   |            ---   ^^^^^^ expected opaque type, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:23:5
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the found opaque type
+...
+LL | fn foo2() -> u32 {
+   |              --- expected `u32` because of return type
+...
+LL |     y
+   |     ^ expected `u32`, found opaque type
+   |
+   = note:     expected type `u32`
+           found opaque type `impl Debug`
+
+error: could not find defining uses
+  --> $DIR/type_of_a_let.rs:8:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs
new file mode 100644
index 00000000000..33d3f164ce1
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let2.rs
@@ -0,0 +1,25 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME This should be under a feature flag
+
+use std::fmt::Debug;
+
+fn foo1() -> u32 {
+    let x: impl Debug = 22_u32;
+    //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
+    x // ERROR: we only know x: Debug, we don't know x = u32
+}
+
+fn foo2() -> u32 {
+    let x: impl Debug = 22_u32;
+    //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
+    let y: impl Debug = x;
+    //~^ ERROR: `impl Trait` not allowed outside of function and method return types [E0562]
+    same_type((x, y)); // ERROR
+    x
+}
+
+fn same_type<T>(x: (T, T)) {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr
new file mode 100644
index 00000000000..7a1825a8e2d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type_of_a_let2.stderr
@@ -0,0 +1,21 @@
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/type_of_a_let2.rs:9:12
+   |
+LL |     let x: impl Debug = 22_u32;
+   |            ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/type_of_a_let2.rs:15:12
+   |
+LL |     let x: impl Debug = 22_u32;
+   |            ^^^^^^^^^^
+
+error[E0562]: `impl Trait` not allowed outside of function and method return types
+  --> $DIR/type_of_a_let2.rs:17:12
+   |
+LL |     let y: impl Debug = x;
+   |            ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0562`.