From 40f5ab1c7532a17e5765535150b228a8bcffef97 Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Tue, 11 Jan 2022 21:56:10 +0000
Subject: [PATCH 01/14] Detect `::` -> `:` typo in type argument

When writing `Vec<A:B>`, suggest `Vec<A::B>`.
---
 compiler/rustc_resolve/src/late.rs            |  6 ++-
 .../rustc_resolve/src/late/diagnostics.rs     | 37 +++++++++++++++
 ...type-ascription-instead-of-path-in-type.rs | 14 ++++++
 ...-ascription-instead-of-path-in-type.stderr | 46 +++++++++++++++++++
 4 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs
 create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 1b02511fd7c2f..801fbc049264f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -400,6 +400,8 @@ struct DiagnosticMetadata<'ast> {
 
     /// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
     current_where_predicate: Option<&'ast WherePredicate>,
+
+    current_type_path: Option<&'ast Ty>,
 }
 
 struct LateResolutionVisitor<'a, 'b, 'ast> {
@@ -472,8 +474,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     }
     fn visit_ty(&mut self, ty: &'ast Ty) {
         let prev = self.diagnostic_metadata.current_trait_object;
+        let prev_ty = self.diagnostic_metadata.current_type_path;
         match ty.kind {
             TyKind::Path(ref qself, ref path) => {
+                self.diagnostic_metadata.current_type_path = Some(ty);
                 self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
             }
             TyKind::ImplicitSelf => {
@@ -490,6 +494,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
         }
         visit::walk_ty(self, ty);
         self.diagnostic_metadata.current_trait_object = prev;
+        self.diagnostic_metadata.current_type_path = prev_ty;
     }
     fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
         self.smart_resolve_path(
@@ -1897,7 +1902,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 let instead = res.is_some();
                 let suggestion =
                     if res.is_none() { this.report_missing_type_error(path) } else { None };
-                // get_from_node_id
 
                 this.r.use_injections.push(UseError {
                     err,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 4cd1b34bedc95..e3f7cea06a391 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 
 use std::iter;
+use std::ops::Deref;
 
 use tracing::debug;
 
@@ -265,6 +266,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             }
         }
 
+        self.detect_assoct_type_constraint_meant_as_path(base_span, &mut err);
+
         // Emit special messages for unresolved `Self` and `self`.
         if is_self_type(path, ns) {
             err.code(rustc_errors::error_code!(E0411));
@@ -603,6 +606,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         (err, candidates)
     }
 
+    fn detect_assoct_type_constraint_meant_as_path(
+        &self,
+        base_span: Span,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        let Some(ty) = self.diagnostic_metadata.current_type_path else { return; };
+        let TyKind::Path(_, path) = &ty.kind else { return; };
+        for segment in &path.segments {
+            let Some(params) = &segment.args else { continue; };
+            let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; };
+            for param in &params.args {
+                let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; };
+                let ast::AssocTyConstraintKind::Bound { bounds } = &constraint.kind else {
+                    continue;
+                };
+                for bound in bounds {
+                    let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)
+                        = bound else
+                    {
+                        continue;
+                    };
+                    if base_span == trait_ref.span {
+                        err.span_suggestion_verbose(
+                            constraint.ident.span.between(trait_ref.span),
+                            "you might have meant to write a path instead of an associated type bound",
+                            "::".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn get_single_associated_item(
         &mut self,
         path: &[Segment],
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs
new file mode 100644
index 0000000000000..48d19f6dd4e3f
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.rs
@@ -0,0 +1,14 @@
+enum A {
+    B,
+}
+
+fn main() {
+    let _: Vec<A:B> = A::B;
+    //~^ ERROR cannot find trait `B` in this scope
+    //~| HELP you might have meant to write a path instead of an associated type bound
+    //~| ERROR associated type bounds are unstable
+    //~| HELP add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+    //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied
+    //~| HELP add missing generic argument
+    //~| ERROR associated type bindings are not allowed here
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
new file mode 100644
index 0000000000000..951ff23d63563
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
@@ -0,0 +1,46 @@
+error[E0405]: cannot find trait `B` in this scope
+  --> $DIR/type-ascription-instead-of-path-in-type.rs:6:18
+   |
+LL |     let _: Vec<A:B> = A::B;
+   |                  ^ not found in this scope
+   |
+help: you might have meant to write a path instead of an associated type bound
+   |
+LL |     let _: Vec<A::B> = A::B;
+   |                 ~~
+
+error[E0658]: associated type bounds are unstable
+  --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16
+   |
+LL |     let _: Vec<A:B> = A::B;
+   |                ^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied
+  --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12
+   |
+LL |     let _: Vec<A:B> = A::B;
+   |            ^^^ expected at least 1 generic argument
+   |
+note: struct defined here, with at least 1 generic parameter: `T`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+   |            ^^^ -
+help: add missing generic argument
+   |
+LL |     let _: Vec<T, A:B> = A::B;
+   |                ++
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16
+   |
+LL |     let _: Vec<A:B> = A::B;
+   |                ^^^ associated type not allowed here
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0107, E0229, E0405, E0658.
+For more information about an error, try `rustc --explain E0107`.

From 2f1a12f8b736336ffd1923f413a7229999b4f81d Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu@gmail.com>
Date: Thu, 6 Jan 2022 13:18:59 +0100
Subject: [PATCH 02/14] Update rust-by-examples

---
 src/doc/rust-by-example | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 1ca6a7bd1d73e..18c0055b8aea4 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 1ca6a7bd1d73edc4a3e6c7d6a40f5d4b66c1e517
+Subproject commit 18c0055b8aea49391e8f758a4400097999c9cf1e

From 5eb6fff8249c8d1262d50a1bd26a28671d6f8487 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu@gmail.com>
Date: Thu, 6 Jan 2022 14:39:42 +0100
Subject: [PATCH 03/14] Add links to the reference and rust by example for asm!
 docs and lints

---
 compiler/rustc_lint/src/builtin.rs      |  3 +++
 compiler/rustc_lint/src/context.rs      |  1 +
 compiler/rustc_lint_defs/src/builtin.rs |  4 +++
 library/core/src/lib.rs                 | 12 +++++++++
 src/test/ui/asm/named-asm-labels.stderr | 36 +++++++++++++++++++++++++
 5 files changed, 56 insertions(+)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 66a89492abd84..56e6c4b059562 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -3158,7 +3158,10 @@ declare_lint! {
     /// 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 explanation in [Rust By Example] for more details.
+    ///
     /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
+    /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels
     pub NAMED_ASM_LABELS,
     Deny,
     "named labels in inline assembly",
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 69c376c6169ba..d93866443a00e 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -770,6 +770,7 @@ pub trait LintContext: Sized {
                 }
                 BuiltinLintDiagnostics::NamedAsmLabel(help) => {
                     db.help(&help);
+                    db.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
                 }
             }
             // Rewrap `db`, and pass control to the user.
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index c2f6118227a4a..4865b016d0ee2 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2456,6 +2456,10 @@ declare_lint! {
     /// register size, to alert you of possibly using the incorrect width. To
     /// fix this, add the suggested modifier to the template, or cast the
     /// value to the correct size.
+    ///
+    /// See [register template modifiers] in the reference for more details.
+    ///
+    /// [register template modifiers]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html#template-modifiers
     pub ASM_SUB_REGISTER,
     Warn,
     "using only a subset of a register for inline asm inputs",
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index d8ac816fb15a0..ade888ed26e61 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -374,6 +374,12 @@ pub mod arch {
     pub use crate::core_arch::arch::*;
 
     /// Inline assembly.
+    ///
+    /// Refer to [rust by example] for a usage guide and the [reference] for
+    /// detailed information about the syntax and available options.
+    ///
+    /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+    /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
     #[stable(feature = "asm", since = "1.59.0")]
     #[rustc_builtin_macro]
     pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
@@ -381,6 +387,12 @@ pub mod arch {
     }
 
     /// Module-level inline assembly.
+    ///
+    /// Refer to [rust by example] for a usage guide and the [reference] for
+    /// detailed information about the syntax and available options.
+    ///
+    /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+    /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
     #[stable(feature = "global_asm", since = "1.59.0")]
     #[rustc_builtin_macro]
     pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr
index b8ff42d86b564..001601497a272 100644
--- a/src/test/ui/asm/named-asm-labels.stderr
+++ b/src/test/ui/asm/named-asm-labels.stderr
@@ -6,6 +6,7 @@ LL |         asm!("bar: nop");
    |
    = note: `#[deny(named_asm_labels)]` on by default
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:27:15
@@ -14,6 +15,7 @@ LL |         asm!("abcd:");
    |               ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:30:15
@@ -22,6 +24,7 @@ LL |         asm!("foo: bar1: nop");
    |               ^^^  ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:34:15
@@ -30,6 +33,7 @@ LL |         asm!("foo1: nop", "nop");
    |               ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:35:15
@@ -38,6 +42,7 @@ LL |         asm!("foo2: foo3: nop", "nop");
    |               ^^^^  ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:37:22
@@ -46,6 +51,7 @@ LL |         asm!("nop", "foo4: nop");
    |                      ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:38:15
@@ -54,6 +60,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    |               ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:38:28
@@ -62,6 +69,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    |                            ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:43:15
@@ -70,6 +78,7 @@ LL |         asm!("foo7: nop; foo8: nop");
    |               ^^^^       ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:45:15
@@ -78,6 +87,7 @@ LL |         asm!("foo9: nop; nop");
    |               ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:46:20
@@ -86,6 +96,7 @@ LL |         asm!("nop; foo10: nop");
    |                    ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:49:15
@@ -94,6 +105,7 @@ LL |         asm!("bar2: nop\n bar3: nop");
    |               ^^^^        ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:51:15
@@ -102,6 +114,7 @@ LL |         asm!("bar4: nop\n nop");
    |               ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:52:21
@@ -110,6 +123,7 @@ LL |         asm!("nop\n bar5: nop");
    |                     ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:53:21
@@ -118,6 +132,7 @@ LL |         asm!("nop\n bar6: bar7: nop");
    |                     ^^^^  ^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:59:13
@@ -128,6 +143,7 @@ LL |             blah3: nop
    |             ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:68:19
@@ -136,6 +152,7 @@ LL |             nop ; blah4: nop
    |                   ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:82:15
@@ -144,6 +161,7 @@ LL |         asm!("blah1: 2bar: nop");
    |               ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:85:15
@@ -152,6 +170,7 @@ LL |         asm!("def: def: nop");
    |               ^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:86:15
@@ -160,6 +179,7 @@ LL |         asm!("def: nop\ndef: nop");
    |               ^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:87:15
@@ -168,6 +188,7 @@ LL |         asm!("def: nop; def: nop");
    |               ^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:95:15
@@ -176,6 +197,7 @@ LL |         asm!("fooo\u{003A} nop");
    |               ^^^^^^^^^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:96:15
@@ -184,6 +206,7 @@ LL |         asm!("foooo\x3A nop");
    |               ^^^^^^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:99:15
@@ -192,6 +215,7 @@ LL |         asm!("fooooo:\u{000A} nop");
    |               ^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:100:15
@@ -200,6 +224,7 @@ LL |         asm!("foooooo:\x0A nop");
    |               ^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:104:14
@@ -208,6 +233,7 @@ LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:112:13
@@ -216,6 +242,7 @@ LL |             ab: nop // ab: does foo
    |             ^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:124:14
@@ -224,6 +251,7 @@ LL |         asm!(include_str!("named-asm-labels.s"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 warning: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:134:19
@@ -237,6 +265,7 @@ note: the lint level is defined here
 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 Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:143:20
@@ -245,6 +274,7 @@ LL |     unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noret
    |                    ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:149:20
@@ -253,6 +283,7 @@ LL |     unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret
    |                    ^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:157:20
@@ -261,6 +292,7 @@ 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 Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:167:24
@@ -269,6 +301,7 @@ 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 Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:176:15
@@ -277,6 +310,7 @@ LL |         asm!("closure1: nop");
    |               ^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:180:15
@@ -285,6 +319,7 @@ LL |         asm!("closure2: nop");
    |               ^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
   --> $DIR/named-asm-labels.rs:190:19
@@ -293,6 +328,7 @@ LL |             asm!("closure3: nop");
    |                   ^^^^^^^^
    |
    = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: aborting due to 35 previous errors; 1 warning emitted
 

From 19dd2ecc2d49e2adfeb1211c038b0d35be42ec33 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Mon, 24 Jan 2022 13:45:34 +0100
Subject: [PATCH 04/14] Reorder unwinding related builder methods to
 differentiate between dwarf and msvc instructions

---
 compiler/rustc_codegen_gcc/src/builder.rs        |  8 ++++----
 compiler/rustc_codegen_llvm/src/builder.rs       | 12 ++++++------
 compiler/rustc_codegen_ssa/src/traits/builder.rs |  6 +++++-
 3 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 379c88bbd40fa..1b9e13873b0b9 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1256,6 +1256,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         aggregate_value
     }
 
+    fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
+        // TODO(antoyo)
+    }
+
     fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> {
         let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1");
         let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
@@ -1295,10 +1299,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
-    fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
-        // TODO(antoyo)
-    }
-
     // Atomic Operations
     fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
         let expected = self.current_func().new_local(None, cmp.get_type(), "expected");
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 8a9450c20dda4..efae50b37a8c6 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -956,6 +956,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, UNNAMED) }
     }
 
+    fn set_personality_fn(&mut self, personality: &'ll Value) {
+        unsafe {
+            llvm::LLVMSetPersonalityFn(self.llfn(), personality);
+        }
+    }
+
     fn landing_pad(
         &mut self,
         ty: &'ll Type,
@@ -1044,12 +1050,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn set_personality_fn(&mut self, personality: &'ll Value) {
-        unsafe {
-            llvm::LLVMSetPersonalityFn(self.llfn(), personality);
-        }
-    }
-
     // Atomic Operations
     fn atomic_cmpxchg(
         &mut self,
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 5a06fb4610587..98c67154f9b3a 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -421,6 +421,9 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
     fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
 
+    fn set_personality_fn(&mut self, personality: Self::Value);
+
+    // These are used by everyone except msvc
     fn landing_pad(
         &mut self,
         ty: Self::Type,
@@ -429,6 +432,8 @@ pub trait BuilderMethods<'a, 'tcx>:
     ) -> Self::Value;
     fn set_cleanup(&mut self, landing_pad: Self::Value);
     fn resume(&mut self, exn: Self::Value) -> Self::Value;
+
+    // These are used only by msvc
     fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
     fn cleanup_ret(
         &mut self,
@@ -443,7 +448,6 @@ pub trait BuilderMethods<'a, 'tcx>:
         num_handlers: usize,
     ) -> Self::Value;
     fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock);
-    fn set_personality_fn(&mut self, personality: Self::Value);
 
     fn atomic_cmpxchg(
         &mut self,

From e9646fa76b4876cbfe50fd89d3f179c27685f874 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Mon, 24 Jan 2022 13:48:09 +0100
Subject: [PATCH 05/14] Remove unused return values from resume and cleanup_ret

Given that these instructions are diverging, not every codegen backend
may be able to produce a return value for them.
---
 compiler/rustc_codegen_gcc/src/builder.rs     |  4 ++--
 compiler/rustc_codegen_llvm/src/builder.rs    | 19 +++++++++----------
 .../rustc_codegen_ssa/src/traits/builder.rs   |  8 ++------
 3 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 1b9e13873b0b9..d3fdfccd8a5d2 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1275,7 +1275,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // TODO(antoyo)
     }
 
-    fn resume(&mut self, _exn: RValue<'gcc>) -> RValue<'gcc> {
+    fn resume(&mut self, _exn: RValue<'gcc>) {
         unimplemented!();
     }
 
@@ -1283,7 +1283,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
-    fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) -> RValue<'gcc> {
+    fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option<Block<'gcc>>) {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index efae50b37a8c6..7d62e5e8d417c 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -983,8 +983,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
-        unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) }
+    fn resume(&mut self, exn: &'ll Value) {
+        unsafe {
+            llvm::LLVMBuildResume(self.llbuilder, exn);
+        }
     }
 
     fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
@@ -1001,14 +1003,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         Funclet::new(ret.expect("LLVM does not have support for cleanuppad"))
     }
 
-    fn cleanup_ret(
-        &mut self,
-        funclet: &Funclet<'ll>,
-        unwind: Option<&'ll BasicBlock>,
-    ) -> &'ll Value {
-        let ret =
-            unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) };
-        ret.expect("LLVM does not have support for cleanupret")
+    fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) {
+        unsafe {
+            llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
+                .expect("LLVM does not have support for cleanupret");
+        }
     }
 
     fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 98c67154f9b3a..f10d7c01df006 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -431,15 +431,11 @@ pub trait BuilderMethods<'a, 'tcx>:
         num_clauses: usize,
     ) -> Self::Value;
     fn set_cleanup(&mut self, landing_pad: Self::Value);
-    fn resume(&mut self, exn: Self::Value) -> Self::Value;
+    fn resume(&mut self, exn: Self::Value);
 
     // These are used only by msvc
     fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
-    fn cleanup_ret(
-        &mut self,
-        funclet: &Self::Funclet,
-        unwind: Option<Self::BasicBlock>,
-    ) -> Self::Value;
+    fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>);
     fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
     fn catch_switch(
         &mut self,

From 7a164509d3ed0b7dfc5f79b2e0053a4abef5fb1b Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Mon, 24 Jan 2022 13:50:12 +0100
Subject: [PATCH 06/14] Merge add_handler into catch_switch

Some codegen backends may require all handlers to be immediately known
---
 compiler/rustc_codegen_gcc/src/builder.rs        | 11 ++++++-----
 compiler/rustc_codegen_llvm/src/builder.rs       | 16 ++++++++--------
 compiler/rustc_codegen_llvm/src/intrinsic.rs     |  5 ++---
 compiler/rustc_codegen_ssa/src/mir/block.rs      |  3 +--
 compiler/rustc_codegen_ssa/src/traits/builder.rs |  3 +--
 5 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index d3fdfccd8a5d2..185aa3a5b4090 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1291,11 +1291,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
-    fn catch_switch(&mut self, _parent: Option<RValue<'gcc>>, _unwind: Option<Block<'gcc>>, _num_handlers: usize) -> RValue<'gcc> {
-        unimplemented!();
-    }
-
-    fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) {
+    fn catch_switch(
+        &mut self,
+        _parent: Option<RValue<'gcc>>,
+        _unwind: Option<Block<'gcc>>,
+        _handlers: &[Block<'gcc>],
+    ) -> RValue<'gcc> {
         unimplemented!();
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 7d62e5e8d417c..02b9f23c4d6a6 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1028,7 +1028,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         parent: Option<&'ll Value>,
         unwind: Option<&'ll BasicBlock>,
-        num_handlers: usize,
+        handlers: &[&'ll BasicBlock],
     ) -> &'ll Value {
         let name = cstr!("catchswitch");
         let ret = unsafe {
@@ -1036,17 +1036,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 self.llbuilder,
                 parent,
                 unwind,
-                num_handlers as c_uint,
+                handlers.len() as c_uint,
                 name.as_ptr(),
             )
         };
-        ret.expect("LLVM does not have support for catchswitch")
-    }
-
-    fn add_handler(&mut self, catch_switch: &'ll Value, handler: &'ll BasicBlock) {
-        unsafe {
-            llvm::LLVMRustAddHandler(catch_switch, handler);
+        let ret = ret.expect("LLVM does not have support for catchswitch");
+        for handler in handlers {
+            unsafe {
+                llvm::LLVMRustAddHandler(ret, handler);
+            }
         }
+        ret
     }
 
     // Atomic Operations
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 5adfa18035a0e..f51d014bfb39a 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -525,9 +525,8 @@ fn codegen_msvc_try<'ll>(
 
         normal.ret(bx.const_i32(0));
 
-        let cs = catchswitch.catch_switch(None, None, 2);
-        catchswitch.add_handler(cs, catchpad_rust.llbb());
-        catchswitch.add_handler(cs, catchpad_foreign.llbb());
+        let cs =
+            catchswitch.catch_switch(None, None, &[catchpad_rust.llbb(), catchpad_foreign.llbb()]);
 
         // We can't use the TypeDescriptor defined in libpanic_unwind because it
         // might be in another DLL and the SEH encoding only supports specifying
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index b1a76b80002db..ee7ca7f6e4661 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1346,8 +1346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb));
                     ret_llbb = cs_bx.llbb();
 
-                    let cs = cs_bx.catch_switch(None, None, 1);
-                    cs_bx.add_handler(cs, cp_bx.llbb());
+                    let cs = cs_bx.catch_switch(None, None, &[cp_bx.llbb()]);
 
                     // The "null" here is actually a RTTI type descriptor for the
                     // C++ personality function, but `catch (...)` has no type so
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index f10d7c01df006..6c88241350f9d 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -441,9 +441,8 @@ pub trait BuilderMethods<'a, 'tcx>:
         &mut self,
         parent: Option<Self::Value>,
         unwind: Option<Self::BasicBlock>,
-        num_handlers: usize,
+        handlers: &[Self::BasicBlock],
     ) -> Self::Value;
-    fn add_handler(&mut self, catch_switch: Self::Value, handler: Self::BasicBlock);
 
     fn atomic_cmpxchg(
         &mut self,

From f6ce7711726c24025083aec429d6e30274d63476 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Mon, 24 Jan 2022 13:57:32 +0100
Subject: [PATCH 07/14] Merge landing_pad and set_cleanup into
 cleanup_landing_pad

---
 compiler/rustc_codegen_gcc/src/builder.rs     |  6 +---
 compiler/rustc_codegen_llvm/src/builder.rs    | 34 ++++++++++---------
 compiler/rustc_codegen_ssa/src/mir/block.rs   |  3 +-
 .../rustc_codegen_ssa/src/traits/builder.rs   |  8 +----
 4 files changed, 21 insertions(+), 30 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 185aa3a5b4090..ffb77e16a1486 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1260,7 +1260,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // TODO(antoyo)
     }
 
-    fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> {
+    fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
         let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1");
         let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
         let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
@@ -1271,10 +1271,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
     }
 
-    fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) {
-        // TODO(antoyo)
-    }
-
     fn resume(&mut self, _exn: RValue<'gcc>) {
         unimplemented!();
     }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 02b9f23c4d6a6..c9a04e6280f40 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -962,25 +962,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn landing_pad(
-        &mut self,
-        ty: &'ll Type,
-        pers_fn: &'ll Value,
-        num_clauses: usize,
-    ) -> &'ll Value {
-        // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while,
-        // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The
-        // personality lives on the parent function anyway.
-        self.set_personality_fn(pers_fn);
-        unsafe {
-            llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED)
-        }
-    }
-
-    fn set_cleanup(&mut self, landing_pad: &'ll Value) {
+    fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value {
+        let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
+        landing_pad
     }
 
     fn resume(&mut self, exn: &'ll Value) {
@@ -1477,4 +1464,19 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             None
         }
     }
+
+    pub(crate) fn landing_pad(
+        &mut self,
+        ty: &'ll Type,
+        pers_fn: &'ll Value,
+        num_clauses: usize,
+    ) -> &'ll Value {
+        // Use LLVMSetPersonalityFn to set the personality. It supports arbitrary Consts while,
+        // LLVMBuildLandingPad requires the argument to be a Function (as of LLVM 12). The
+        // personality lives on the parent function anyway.
+        self.set_personality_fn(pers_fn);
+        unsafe {
+            llvm::LLVMBuildLandingPad(self.llbuilder, ty, None, num_clauses as c_uint, UNNAMED)
+        }
+    }
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index ee7ca7f6e4661..4c7a09ca1e94b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1373,8 +1373,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             let llpersonality = self.cx.eh_personality();
             let llretty = self.landing_pad_type();
-            let lp = bx.landing_pad(llretty, llpersonality, 1);
-            bx.set_cleanup(lp);
+            let lp = bx.cleanup_landing_pad(llretty, llpersonality);
 
             let slot = self.get_personality_slot(&mut bx);
             slot.storage_live(&mut bx);
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 6c88241350f9d..53fb21b269a12 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -424,13 +424,7 @@ pub trait BuilderMethods<'a, 'tcx>:
     fn set_personality_fn(&mut self, personality: Self::Value);
 
     // These are used by everyone except msvc
-    fn landing_pad(
-        &mut self,
-        ty: Self::Type,
-        pers_fn: Self::Value,
-        num_clauses: usize,
-    ) -> Self::Value;
-    fn set_cleanup(&mut self, landing_pad: Self::Value);
+    fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value;
     fn resume(&mut self, exn: Self::Value);
 
     // These are used only by msvc

From 84c0c9d20dbe1d171e6aaf61b8e512d6dc78412f Mon Sep 17 00:00:00 2001
From: Chris Denton <christophersdenton@gmail.com>
Date: Tue, 25 Jan 2022 10:36:10 +0000
Subject: [PATCH 08/14] Avoid double panics when using `TempDir` in tests

---
 library/std/src/sys_common/io.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/library/std/src/sys_common/io.rs b/library/std/src/sys_common/io.rs
index ea9108f17133a..d1e9fed41fc93 100644
--- a/library/std/src/sys_common/io.rs
+++ b/library/std/src/sys_common/io.rs
@@ -8,6 +8,7 @@ pub mod test {
     use crate::env;
     use crate::fs;
     use crate::path::{Path, PathBuf};
+    use crate::thread;
     use rand::RngCore;
 
     pub struct TempDir(PathBuf);
@@ -29,7 +30,12 @@ pub mod test {
             // Gee, seeing how we're testing the fs module I sure hope that we
             // at least implement this correctly!
             let TempDir(ref p) = *self;
-            fs::remove_dir_all(p).unwrap();
+            let result = fs::remove_dir_all(p);
+            // Avoid panicking while panicking as this causes the process to
+            // immediately abort, without displaying test results.
+            if !thread::panicking() {
+                result.unwrap();
+            }
         }
     }
 

From a6c0a3d9c2ff361a5f76175564b3c72e23cfcd54 Mon Sep 17 00:00:00 2001
From: Michael Watzko <michael@watzko.de>
Date: Wed, 26 Jan 2022 22:00:26 +0100
Subject: [PATCH 09/14] Unimpl {Add,Sub,Mul,Div,Rem,BitXor,BitOr,BitAnd}<$t>
 for Saturating<$t>

Analog to 9648b313cc8896970a12f45b3bb5c0593c3d510f #93208
---
 library/core/src/num/saturating.rs | 130 ++---------------------------
 1 file changed, 8 insertions(+), 122 deletions(-)

diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs
index 317555034756d..8982473b2dc03 100644
--- a/library/core/src/num/saturating.rs
+++ b/library/core/src/num/saturating.rs
@@ -217,18 +217,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl Add<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn add(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0.saturating_add(other))
-            }
-        }
-        forward_ref_binop! { impl Add, add for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl AddAssign for Saturating<$t> {
             #[inline]
@@ -242,7 +230,7 @@ macro_rules! saturating_impl {
         impl AddAssign<$t> for Saturating<$t> {
             #[inline]
             fn add_assign(&mut self, other: $t) {
-                *self = *self + other;
+                *self = *self + Saturating(other);
             }
         }
         forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t }
@@ -259,18 +247,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl Sub<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn sub(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0.saturating_sub(other))
-            }
-        }
-        forward_ref_binop! { impl Sub, sub for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl SubAssign for Saturating<$t> {
             #[inline]
@@ -284,7 +260,7 @@ macro_rules! saturating_impl {
         impl SubAssign<$t> for Saturating<$t> {
             #[inline]
             fn sub_assign(&mut self, other: $t) {
-                *self = *self - other;
+                *self = *self - Saturating(other);
             }
         }
         forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t }
@@ -301,18 +277,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl Mul<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn mul(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0.saturating_mul(other))
-            }
-        }
-        forward_ref_binop! { impl Mul, mul for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl MulAssign for Saturating<$t> {
             #[inline]
@@ -326,7 +290,7 @@ macro_rules! saturating_impl {
         impl MulAssign<$t> for Saturating<$t> {
             #[inline]
             fn mul_assign(&mut self, other: $t) {
-                *self = *self * other;
+                *self = *self * Saturating(other);
             }
         }
         forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, $t }
@@ -362,36 +326,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        /// # Examples
-        ///
-        /// Basic usage:
-        ///
-        /// ```
-        /// #![feature(saturating_int_impl, saturating_int_assign_impl)]
-        /// use std::num::Saturating;
-        ///
-        #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / 2);")]
-        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MAX), Saturating(", stringify!($t), "::MAX) / 1);")]
-        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN), Saturating(", stringify!($t), "::MIN) / 1);")]
-        /// ```
-        ///
-        /// ```should_panic
-        /// #![feature(saturating_int_impl, saturating_int_assign_impl)]
-        /// use std::num::Saturating;
-        ///
-        #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / 0;")]
-        /// ```
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl Div<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn div(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0.saturating_div(other))
-            }
-        }
-        forward_ref_binop! { impl Div, div for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
 
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl DivAssign for Saturating<$t> {
@@ -406,7 +340,7 @@ macro_rules! saturating_impl {
         impl DivAssign<$t> for Saturating<$t> {
             #[inline]
             fn div_assign(&mut self, other: $t) {
-                *self = *self / other;
+                *self = *self / Saturating(other);
             }
         }
         forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t }
@@ -423,18 +357,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl Rem<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn rem(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0.rem(other))
-            }
-        }
-        forward_ref_binop! { impl Rem, rem for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl RemAssign for Saturating<$t> {
             #[inline]
@@ -448,7 +370,7 @@ macro_rules! saturating_impl {
         impl RemAssign<$t> for Saturating<$t> {
             #[inline]
             fn rem_assign(&mut self, other: $t) {
-                *self = *self % other;
+                *self = *self % Saturating(other);
             }
         }
         forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t }
@@ -477,18 +399,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl BitXor<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn bitxor(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0 ^ other)
-            }
-        }
-        forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl BitXorAssign for Saturating<$t> {
             #[inline]
@@ -502,7 +412,7 @@ macro_rules! saturating_impl {
         impl BitXorAssign<$t> for Saturating<$t> {
             #[inline]
             fn bitxor_assign(&mut self, other: $t) {
-                *self = *self ^ other;
+                *self = *self ^ Saturating(other);
             }
         }
         forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t }
@@ -519,18 +429,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl BitOr<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn bitor(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0 | other)
-            }
-        }
-        forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl BitOrAssign for Saturating<$t> {
             #[inline]
@@ -544,7 +442,7 @@ macro_rules! saturating_impl {
         impl BitOrAssign<$t> for Saturating<$t> {
             #[inline]
             fn bitor_assign(&mut self, other: $t) {
-                *self = *self | other;
+                *self = *self | Saturating(other);
             }
         }
         forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t }
@@ -561,18 +459,6 @@ macro_rules! saturating_impl {
         forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>,
                 #[unstable(feature = "saturating_int_impl", issue = "87920")] }
 
-        #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
-        impl BitAnd<$t> for Saturating<$t> {
-            type Output = Saturating<$t>;
-
-            #[inline]
-            fn bitand(self, other: $t) -> Saturating<$t> {
-                Saturating(self.0 & other)
-            }
-        }
-        forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, $t,
-                #[unstable(feature = "saturating_int_assign_impl", issue = "92354")] }
-
         #[unstable(feature = "saturating_int_impl", issue = "87920")]
         impl BitAndAssign for Saturating<$t> {
             #[inline]
@@ -586,7 +472,7 @@ macro_rules! saturating_impl {
         impl BitAndAssign<$t> for Saturating<$t> {
             #[inline]
             fn bitand_assign(&mut self, other: $t) {
-                *self = *self & other;
+                *self = *self & Saturating(other);
             }
         }
         forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, $t }

From db097f308af6b6ec219a460385159985256e2193 Mon Sep 17 00:00:00 2001
From: Kvicii <Karonazaba@gmail.com>
Date: Thu, 27 Jan 2022 22:07:17 +0800
Subject: [PATCH 10/14] fix typo `documenation`

---
 src/doc/rustdoc/src/references.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustdoc/src/references.md b/src/doc/rustdoc/src/references.md
index b0e2437392c95..bccc2f8e8fa90 100644
--- a/src/doc/rustdoc/src/references.md
+++ b/src/doc/rustdoc/src/references.md
@@ -16,7 +16,7 @@ If you know of other great resources, please submit a pull request!
 - [Github tagged RFCs]
 - [Github tagged issues]
 - [RFC (stalled) front page styleguide]
-- [Guide on how to write documenation for a Rust crate]
+- [Guide on how to write documentation for a Rust crate]
 
 
 [API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html

From ff79ce7e6fa0d65a208245d92857bf2c2a14599e Mon Sep 17 00:00:00 2001
From: Kvicii <Karonazaba@gmail.com>
Date: Fri, 28 Jan 2022 10:26:49 +0800
Subject: [PATCH 11/14] fix typo `documenation`

---
 src/doc/rustdoc/src/references.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/doc/rustdoc/src/references.md b/src/doc/rustdoc/src/references.md
index bccc2f8e8fa90..45cf4e88eef6b 100644
--- a/src/doc/rustdoc/src/references.md
+++ b/src/doc/rustdoc/src/references.md
@@ -22,7 +22,7 @@ If you know of other great resources, please submit a pull request!
 [API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html
 [Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
 [Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
-[Guide on how to write documenation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate
+[Guide on how to write documentation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate
 [Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
 [RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html
 [RFC 1946: Intra Rustdoc Links]: https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html

From 7c7509bc3b1de8845a00f50b5e21a311b5361dc9 Mon Sep 17 00:00:00 2001
From: pierwill <pierwill@users.noreply.github.com>
Date: Wed, 26 Jan 2022 20:57:46 -0600
Subject: [PATCH 12/14] Edit docs introduction for `std::cmp::PartialOrd`

This makes `PartialOrd` consistent with the other three traits in this
module, which all include links to their respective mathematical concepts
on Wikipedia.
---
 library/core/src/cmp.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 1af352d542ac6..a3e7747991190 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -880,7 +880,7 @@ impl PartialOrd for Ordering {
     }
 }
 
-/// Trait for values that can be compared for a sort-order.
+/// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order).
 ///
 /// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
 /// the `<`, `<=`, `>`, and `>=` operators, respectively.

From 00cbc8d0c820b8ba09c73fe538852e1ee7d5d8d0 Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@profian.com>
Date: Fri, 21 Jan 2022 14:19:13 +0100
Subject: [PATCH 13/14] wasi: update to wasi 0.11.0

To make use of `sock_accept()`, update the wasi crate to `0.11.0`.

Signed-off-by: Harald Hoyer <harald@profian.com>
---
 Cargo.lock                         | 12 ++++++---
 library/std/Cargo.toml             |  2 +-
 library/std/src/os/wasi/fs.rs      | 15 +++++++++++
 library/std/src/sys/wasi/mod.rs    | 41 ++++++++++++++++--------------
 library/std/src/sys/wasi/stdio.rs  |  2 +-
 library/std/src/sys/wasi/thread.rs |  8 +++---
 library/std/src/sys/wasi/time.rs   |  2 +-
 7 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 738f33d3fa219..ab88bbe1491f0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1473,7 +1473,7 @@ checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
 dependencies = [
  "cfg-if 0.1.10",
  "libc",
- "wasi",
+ "wasi 0.9.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -1484,7 +1484,7 @@ checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
 dependencies = [
  "cfg-if 0.1.10",
  "libc",
- "wasi",
+ "wasi 0.9.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -4854,7 +4854,7 @@ dependencies = [
  "rustc-demangle",
  "std_detect",
  "unwind",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -5612,6 +5612,12 @@ name = "wasi"
 version = "0.9.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 165169aedb315..c54f38615c580 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -45,7 +45,7 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 hermit-abi = { version = "0.1.19", features = ['rustc-dep-of-std'] }
 
 [target.wasm32-wasi.dependencies]
-wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
+wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
 
 [features]
 backtrace = [
diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs
index 5c62679f552d6..37126069f942b 100644
--- a/library/std/src/os/wasi/fs.rs
+++ b/library/std/src/os/wasi/fs.rs
@@ -250,6 +250,21 @@ impl FileExt for fs::File {
     }
 
     fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> {
+        let advice = match advice {
+            a if a == wasi::ADVICE_NORMAL.raw() => wasi::ADVICE_NORMAL,
+            a if a == wasi::ADVICE_SEQUENTIAL.raw() => wasi::ADVICE_SEQUENTIAL,
+            a if a == wasi::ADVICE_RANDOM.raw() => wasi::ADVICE_RANDOM,
+            a if a == wasi::ADVICE_WILLNEED.raw() => wasi::ADVICE_WILLNEED,
+            a if a == wasi::ADVICE_DONTNEED.raw() => wasi::ADVICE_DONTNEED,
+            a if a == wasi::ADVICE_NOREUSE.raw() => wasi::ADVICE_NOREUSE,
+            _ => {
+                return Err(io::Error::new_const(
+                    io::ErrorKind::InvalidInput,
+                    &"invalid parameter 'advice'",
+                ));
+            }
+        };
+
         self.as_inner().as_inner().advise(offset, len, advice)
     }
 
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index 8d62335aae5eb..f878941939ce8 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -61,23 +61,26 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
     if errno > u16::MAX as i32 || errno < 0 {
         return Uncategorized;
     }
-    match errno as u16 {
-        wasi::ERRNO_CONNREFUSED => ConnectionRefused,
-        wasi::ERRNO_CONNRESET => ConnectionReset,
-        wasi::ERRNO_PERM | wasi::ERRNO_ACCES => PermissionDenied,
-        wasi::ERRNO_PIPE => BrokenPipe,
-        wasi::ERRNO_NOTCONN => NotConnected,
-        wasi::ERRNO_CONNABORTED => ConnectionAborted,
-        wasi::ERRNO_ADDRNOTAVAIL => AddrNotAvailable,
-        wasi::ERRNO_ADDRINUSE => AddrInUse,
-        wasi::ERRNO_NOENT => NotFound,
-        wasi::ERRNO_INTR => Interrupted,
-        wasi::ERRNO_INVAL => InvalidInput,
-        wasi::ERRNO_TIMEDOUT => TimedOut,
-        wasi::ERRNO_EXIST => AlreadyExists,
-        wasi::ERRNO_AGAIN => WouldBlock,
-        wasi::ERRNO_NOSYS => Unsupported,
-        wasi::ERRNO_NOMEM => OutOfMemory,
+
+    match errno {
+        e if e == wasi::ERRNO_CONNREFUSED.raw().into() => ConnectionRefused,
+        e if e == wasi::ERRNO_CONNRESET.raw().into() => ConnectionReset,
+        e if e == wasi::ERRNO_PERM.raw().into() || e == wasi::ERRNO_ACCES.raw().into() => {
+            PermissionDenied
+        }
+        e if e == wasi::ERRNO_PIPE.raw().into() => BrokenPipe,
+        e if e == wasi::ERRNO_NOTCONN.raw().into() => NotConnected,
+        e if e == wasi::ERRNO_CONNABORTED.raw().into() => ConnectionAborted,
+        e if e == wasi::ERRNO_ADDRNOTAVAIL.raw().into() => AddrNotAvailable,
+        e if e == wasi::ERRNO_ADDRINUSE.raw().into() => AddrInUse,
+        e if e == wasi::ERRNO_NOENT.raw().into() => NotFound,
+        e if e == wasi::ERRNO_INTR.raw().into() => Interrupted,
+        e if e == wasi::ERRNO_INVAL.raw().into() => InvalidInput,
+        e if e == wasi::ERRNO_TIMEDOUT.raw().into() => TimedOut,
+        e if e == wasi::ERRNO_EXIST.raw().into() => AlreadyExists,
+        e if e == wasi::ERRNO_AGAIN.raw().into() => WouldBlock,
+        e if e == wasi::ERRNO_NOSYS.raw().into() => Unsupported,
+        e if e == wasi::ERRNO_NOMEM.raw().into() => OutOfMemory,
         _ => Uncategorized,
     }
 }
@@ -96,6 +99,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     return ret;
 }
 
-fn err2io(err: wasi::Error) -> std_io::Error {
-    std_io::Error::from_raw_os_error(err.raw_error().into())
+fn err2io(err: wasi::Errno) -> std_io::Error {
+    std_io::Error::from_raw_os_error(err.raw().into())
 }
diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs
index 2c8f394cd47b0..4cc0e4ed5a45a 100644
--- a/library/std/src/sys/wasi/stdio.rs
+++ b/library/std/src/sys/wasi/stdio.rs
@@ -104,7 +104,7 @@ impl io::Write for Stderr {
 pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
 
 pub fn is_ebadf(err: &io::Error) -> bool {
-    err.raw_os_error() == Some(wasi::ERRNO_BADF.into())
+    err.raw_os_error() == Some(wasi::ERRNO_BADF.raw().into())
 }
 
 pub fn panic_output() -> Option<impl io::Write> {
diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs
index 2e4e474c4492c..e7a6ab4be826f 100644
--- a/library/std/src/sys/wasi/thread.rs
+++ b/library/std/src/sys/wasi/thread.rs
@@ -41,8 +41,7 @@ impl Thread {
 
         let in_ = wasi::Subscription {
             userdata: USERDATA,
-            r#type: wasi::EVENTTYPE_CLOCK,
-            u: wasi::SubscriptionU { clock },
+            u: wasi::SubscriptionU { tag: 0, u: wasi::SubscriptionUU { clock } },
         };
         unsafe {
             let mut event: wasi::Event = mem::zeroed();
@@ -51,7 +50,10 @@ impl Thread {
                 (
                     Ok(1),
                     wasi::Event {
-                        userdata: USERDATA, error: 0, r#type: wasi::EVENTTYPE_CLOCK, ..
+                        userdata: USERDATA,
+                        error: wasi::ERRNO_SUCCESS,
+                        type_: wasi::EVENTTYPE_CLOCK,
+                        ..
                     },
                 ) => {}
                 _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
diff --git a/library/std/src/sys/wasi/time.rs b/library/std/src/sys/wasi/time.rs
index 2e720d11603a7..db0ddecf0c629 100644
--- a/library/std/src/sys/wasi/time.rs
+++ b/library/std/src/sys/wasi/time.rs
@@ -10,7 +10,7 @@ pub struct SystemTime(Duration);
 
 pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
 
-fn current_time(clock: u32) -> Duration {
+fn current_time(clock: wasi::Clockid) -> Duration {
     let ts = unsafe {
         wasi::clock_time_get(
             clock, 1, // precision... seems ignored though?

From d2a13693c2858b6b0fe1feb2dfff604bc2b0aa30 Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@profian.com>
Date: Fri, 21 Jan 2022 14:19:48 +0100
Subject: [PATCH 14/14] wasi: enable TcpListener and TcpStream

With the addition of `sock_accept()` to snapshot1, simple networking via
a passed `TcpListener` is possible. This patch implements the basics to
make a simple server work.

Signed-off-by: Harald Hoyer <harald@profian.com>
---
 library/std/src/os/wasi/net/mod.rs | 20 +++++++++
 library/std/src/sys/wasi/fd.rs     |  4 ++
 library/std/src/sys/wasi/net.rs    | 66 ++++++++++++++++++++++++------
 3 files changed, 77 insertions(+), 13 deletions(-)

diff --git a/library/std/src/os/wasi/net/mod.rs b/library/std/src/os/wasi/net/mod.rs
index e6bcf87887f03..73c097d4a50ab 100644
--- a/library/std/src/os/wasi/net/mod.rs
+++ b/library/std/src/os/wasi/net/mod.rs
@@ -1,3 +1,23 @@
 //! WASI-specific networking functionality
 
 #![unstable(feature = "wasi_ext", issue = "71213")]
+
+use crate::io;
+use crate::net;
+use crate::sys_common::AsInner;
+
+/// WASI-specific extensions to [`std::net::TcpListener`].
+///
+/// [`std::net::TcpListener`]: crate::net::TcpListener
+pub trait TcpListenerExt {
+    /// Accept a socket.
+    ///
+    /// This corresponds to the `sock_accept` syscall.
+    fn sock_accept(&self, flags: u16) -> io::Result<u32>;
+}
+
+impl TcpListenerExt for net::TcpListener {
+    fn sock_accept(&self, flags: u16) -> io::Result<u32> {
+        self.as_inner().as_inner().as_inner().sock_accept(flags)
+    }
+}
diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs
index e4f4456611cd0..0b9c8e61db84c 100644
--- a/library/std/src/sys/wasi/fd.rs
+++ b/library/std/src/sys/wasi/fd.rs
@@ -228,6 +228,10 @@ impl WasiFd {
         unsafe { wasi::path_remove_directory(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
     }
 
+    pub fn sock_accept(&self, flags: wasi::Fdflags) -> io::Result<wasi::Fd> {
+        unsafe { wasi::sock_accept(self.as_raw_fd() as wasi::Fd, flags).map_err(err2io) }
+    }
+
     pub fn sock_recv(
         &self,
         ri_data: &mut [IoSliceMut<'_>],
diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs
index a4dbb225376ee..c66e0e4d328ad 100644
--- a/library/std/src/sys/wasi/net.rs
+++ b/library/std/src/sys/wasi/net.rs
@@ -1,5 +1,6 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
+use super::err2io;
 use super::fd::WasiFd;
 use crate::convert::TryFrom;
 use crate::fmt;
@@ -87,24 +88,24 @@ impl TcpStream {
         unsupported()
     }
 
-    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        unsupported()
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.read_vectored(&mut [IoSliceMut::new(buf)])
     }
 
-    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        unsupported()
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.socket().as_inner().read(bufs)
     }
 
     pub fn is_read_vectored(&self) -> bool {
         true
     }
 
-    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        unsupported()
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoSlice::new(buf)])
     }
 
-    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
-        unsupported()
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.socket().as_inner().write(bufs)
     }
 
     pub fn is_write_vectored(&self) -> bool {
@@ -155,8 +156,23 @@ impl TcpStream {
         unsupported()
     }
 
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        unsupported()
+    pub fn set_nonblocking(&self, state: bool) -> io::Result<()> {
+        let fdstat = unsafe {
+            wasi::fd_fdstat_get(self.socket().as_inner().as_raw_fd() as wasi::Fd).map_err(err2io)?
+        };
+
+        let mut flags = fdstat.fs_flags;
+
+        if state {
+            flags |= wasi::FDFLAGS_NONBLOCK;
+        } else {
+            flags &= !wasi::FDFLAGS_NONBLOCK;
+        }
+
+        unsafe {
+            wasi::fd_fdstat_set_flags(self.socket().as_inner().as_raw_fd() as wasi::Fd, flags)
+                .map_err(err2io)
+        }
     }
 
     pub fn socket(&self) -> &Socket {
@@ -194,7 +210,16 @@ impl TcpListener {
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        unsupported()
+        let fd = unsafe {
+            wasi::sock_accept(self.as_inner().as_inner().as_raw_fd() as _, 0).map_err(err2io)?
+        };
+
+        Ok((
+            TcpStream::from_inner(unsafe { Socket::from_raw_fd(fd as _) }),
+            // WASI has no concept of SocketAddr yet
+            // return an unspecified IPv4Addr
+            SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),
+        ))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpListener> {
@@ -221,8 +246,23 @@ impl TcpListener {
         unsupported()
     }
 
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        unsupported()
+    pub fn set_nonblocking(&self, state: bool) -> io::Result<()> {
+        let fdstat = unsafe {
+            wasi::fd_fdstat_get(self.socket().as_inner().as_raw_fd() as wasi::Fd).map_err(err2io)?
+        };
+
+        let mut flags = fdstat.fs_flags;
+
+        if state {
+            flags |= wasi::FDFLAGS_NONBLOCK;
+        } else {
+            flags &= !wasi::FDFLAGS_NONBLOCK;
+        }
+
+        unsafe {
+            wasi::fd_fdstat_set_flags(self.socket().as_inner().as_raw_fd() as wasi::Fd, flags)
+                .map_err(err2io)
+        }
     }
 
     pub fn socket(&self) -> &Socket {