about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-24 02:30:17 +0000
committerbors <bors@rust-lang.org>2024-03-24 02:30:17 +0000
commit548e14b43963882fb758deb89e8258d9b8c2fc2a (patch)
treeff8336cc01e7d2939240a37acba7096caeb19377
parent9b8d12cf4c2311203aea83315552b15993bd4f81 (diff)
parent6f16b41a4b299bfa31355e2d05110f54df93f9d8 (diff)
downloadrust-548e14b43963882fb758deb89e8258d9b8c2fc2a.tar.gz
rust-548e14b43963882fb758deb89e8258d9b8c2fc2a.zip
Auto merge of #122966 - matthiaskrgr:rollup-20k8nsm, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #121281 (regression test for #103626)
 - #122168 (Fix validation on substituted callee bodies in MIR inliner)
 - #122217 (Handle str literals written with `'` lexed as lifetime)
 - #122379 (transmute: caution against int2ptr transmutation)
 - #122840 (`rustdoc --test`: Prevent reaching the maximum size of command-line by using files for arguments if there are too many)
 - #122907 (Uniquify `ReError` on input mode in canonicalizer)
 - #122942 (Add test in higher ranked subtype)
 - #122943 (add a couple more ice tests)
 - #122963 (core/panicking: fix outdated comment)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs19
-rw-r--r--compiler/rustc_infer/messages.ftl2
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs14
-rw-r--r--compiler/rustc_lexer/src/cursor.rs11
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs9
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs3
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs22
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs57
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs20
-rw-r--r--library/core/src/intrinsics.rs41
-rw-r--r--library/core/src/panicking.rs4
-rw-r--r--src/librustdoc/doctest.rs213
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/markdown.rs11
-rw-r--r--src/tools/run-make-support/src/lib.rs41
-rw-r--r--tests/mir-opt/inline_coroutine_body.rs28
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff281
-rw-r--r--tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff341
-rw-r--r--tests/run-make/rustdoc-test-args/foo.rs3
-rw-r--r--tests/run-make/rustdoc-test-args/rmake.rs18
-rw-r--r--tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs26
-rw-r--r--tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr42
-rw-r--r--tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs57
-rw-r--r--tests/ui/drop/norm-ice-106444.rs16
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.rs17
-rw-r--r--tests/ui/higher-ranked/structually-relate-aliases.stderr27
-rw-r--r--tests/ui/impl-trait/recursive-ice-101862.rs12
-rw-r--r--tests/ui/impl-trait/recursive-ice-101862.stderr24
-rw-r--r--tests/ui/inference/str-as-char.stderr12
-rw-r--r--tests/ui/issues/issue-23589.stderr4
-rw-r--r--tests/ui/lexer/lex-bad-char-literals-2.stderr4
-rw-r--r--tests/ui/lexer/lex-bad-char-literals-3.stderr8
-rw-r--r--tests/ui/lexer/lex-bad-char-literals-5.stderr8
-rw-r--r--tests/ui/lexer/lex-bad-char-literals-6.stderr12
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed6
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-1.rs6
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr20
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed4
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-2.rs4
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr13
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-3.rs7
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr14
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr14
-rw-r--r--tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr14
-rw-r--r--tests/ui/nll/ice-106874.rs48
-rw-r--r--tests/ui/nll/ice-106874.stderr90
-rw-r--r--tests/ui/parser/issues/issue-64732.rs2
-rw-r--r--tests/ui/parser/issues/issue-64732.stderr6
-rw-r--r--tests/ui/parser/unicode-character-literal.fixed4
-rw-r--r--tests/ui/parser/unicode-character-literal.rs4
-rw-r--r--tests/ui/parser/unicode-character-literal.stderr8
-rw-r--r--tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs15
-rw-r--r--tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr31
-rw-r--r--tests/ui/specialization/broken-mir-drop-glue-107228.rs28
-rw-r--r--tests/ui/str/str-as-char.stderr4
-rw-r--r--tests/ui/traits/next-solver/dont-canonicalize-re-error.rs28
-rw-r--r--tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr21
-rw-r--r--tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs15
-rw-r--r--tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr33
-rw-r--r--tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs36
-rw-r--r--tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr25
64 files changed, 1757 insertions, 171 deletions
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index c8eeaa4a45e..1664475f52a 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -85,7 +85,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
         cfg_checker.check_cleanup_control_flow();
 
         // Also run the TypeChecker.
-        for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body) {
+        for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) {
             cfg_checker.fail(location, msg);
         }
 
@@ -541,19 +541,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
 
 /// A faster version of the validation pass that only checks those things which may break when
 /// instantiating any generic parameters.
+///
+/// `caller_body` is used to detect cycles in MIR inlining and MIR validation before
+/// `optimized_mir` is available.
 pub fn validate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
     mir_phase: MirPhase,
     param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
+    caller_body: &Body<'tcx>,
 ) -> Vec<(Location, String)> {
-    let mut type_checker = TypeChecker { body, tcx, param_env, mir_phase, failures: Vec::new() };
+    let mut type_checker =
+        TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() };
     type_checker.visit_body(body);
     type_checker.failures
 }
 
 struct TypeChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
+    caller_body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
     mir_phase: MirPhase,
@@ -705,8 +711,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                     &ty::Coroutine(def_id, args) => {
                         let f_ty = if let Some(var) = parent_ty.variant_index {
-                            let gen_body = if def_id == self.body.source.def_id() {
-                                self.body
+                            // If we're currently validating an inlined copy of this body,
+                            // then it will no longer be parameterized over the original
+                            // args of the coroutine. Otherwise, we prefer to use this body
+                            // since we may be in the process of computing this MIR in the
+                            // first place.
+                            let gen_body = if def_id == self.caller_body.source.def_id() {
+                                self.caller_body
                             } else {
                                 self.tcx.optimized_mir(def_id)
                             };
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index e44a6ae3b3f..521c65c6009 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -169,7 +169,7 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
 
 infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
 infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
-infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
+infer_meant_str_literal = if you meant to write a string literal, use double quotes
 infer_mismatched_static_lifetime = incompatible lifetime on type
 infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index a3cf0d8e520..d0b1f2848ff 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1339,15 +1339,12 @@ pub enum TypeErrorAdditionalDiags {
         span: Span,
         code: String,
     },
-    #[suggestion(
-        infer_meant_str_literal,
-        code = "\"{code}\"",
-        applicability = "machine-applicable"
-    )]
+    #[multipart_suggestion(infer_meant_str_literal, applicability = "machine-applicable")]
     MeantStrLiteral {
-        #[primary_span]
-        span: Span,
-        code: String,
+        #[suggestion_part(code = "\"")]
+        start: Span,
+        #[suggestion_part(code = "\"")]
+        end: Span,
     },
     #[suggestion(
         infer_consider_specifying_length,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 4364249100d..82634f7308d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2079,16 +2079,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 // If a string was expected and the found expression is a character literal,
                 // perhaps the user meant to write `"s"` to specify a string literal.
                 (ty::Ref(_, r, _), ty::Char) if r.is_str() => {
-                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
-                        if let Some(code) =
-                            code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
-                        {
-                            suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
-                                span,
-                                code: escape_literal(code),
-                            })
-                        }
-                    }
+                    suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral {
+                        start: span.with_hi(span.lo() + BytePos(1)),
+                        end: span.with_lo(span.hi() - BytePos(1)),
+                    })
                 }
                 // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
                 // we try to suggest to add the missing `let` for `if let Some(..) = expr`
diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs
index aba7f95487e..d173c3ac032 100644
--- a/compiler/rustc_lexer/src/cursor.rs
+++ b/compiler/rustc_lexer/src/cursor.rs
@@ -46,7 +46,7 @@ impl<'a> Cursor<'a> {
     /// If requested position doesn't exist, `EOF_CHAR` is returned.
     /// However, getting `EOF_CHAR` doesn't always mean actual end of file,
     /// it should be checked with `is_eof` method.
-    pub(crate) fn first(&self) -> char {
+    pub fn first(&self) -> char {
         // `.next()` optimizes better than `.nth(0)`
         self.chars.clone().next().unwrap_or(EOF_CHAR)
     }
@@ -59,6 +59,15 @@ impl<'a> Cursor<'a> {
         iter.next().unwrap_or(EOF_CHAR)
     }
 
+    /// Peeks the third symbol from the input stream without consuming it.
+    pub fn third(&self) -> char {
+        // `.next()` optimizes better than `.nth(1)`
+        let mut iter = self.chars.clone();
+        iter.next();
+        iter.next();
+        iter.next().unwrap_or(EOF_CHAR)
+    }
+
     /// Checks if there is nothing more to consume.
     pub(crate) fn is_eof(&self) -> bool {
         self.chars.as_str().is_empty()
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index 000b96ee801..e0bbd582d88 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -64,12 +64,9 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
         let mut by_move_body = body.clone();
         MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body);
         dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
-        by_move_body.source = mir::MirSource {
-            instance: InstanceDef::CoroutineKindShim {
-                coroutine_def_id: coroutine_def_id.to_def_id(),
-            },
-            promoted: None,
-        };
+        by_move_body.source = mir::MirSource::from_instance(InstanceDef::CoroutineKindShim {
+            coroutine_def_id: coroutine_def_id.to_def_id(),
+        });
         body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body);
     }
 }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 4ec76eec3a9..78c0615b165 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -213,6 +213,7 @@ impl<'tcx> Inliner<'tcx> {
             MirPhase::Runtime(RuntimePhase::Optimized),
             self.param_env,
             &callee_body,
+            &caller_body,
         )
         .is_empty()
         {
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index bd23b90fc31..16d8453ea24 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -239,7 +239,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             // FIXME: We should investigate the perf implications of not uniquifying
             // `ReErased`. We may be able to short-circuit registering region
             // obligations if we encounter a `ReErased` on one side, for example.
-            ty::ReStatic | ty::ReErased => match self.canonicalize_mode {
+            ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
                 CanonicalizeMode::Response { .. } => return r,
             },
@@ -277,7 +277,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
                     }
                 }
             }
-            ty::ReError(_) => return r,
         };
 
         let existing_bound_var = match self.canonicalize_mode {
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index e1d26f090e0..aa735f3de1f 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -568,7 +568,7 @@ parse_more_than_one_char = character literal may only contain one codepoint
     .remove_non = consider removing the non-printing characters
     .use_double_quotes = if you meant to write a {$is_byte ->
         [true] byte string
-        *[false] `str`
+        *[false] string
         } literal, use double quotes
 
 parse_multiple_skipped_lines = multiple lines skipped by escaped newline
@@ -833,6 +833,7 @@ parse_unknown_prefix = prefix `{$prefix}` is unknown
     .label = unknown prefix
     .note =  prefixed identifiers and literals are reserved since Rust 2021
     .suggestion_br = use `br` for a raw byte string
+    .suggestion_str = if you meant to write a string literal, use double quotes
     .suggestion_whitespace = consider inserting whitespace here
 
 parse_unknown_start_of_token = unknown start of token: {$escaped}
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 5cad3a568ee..20ebfc6691b 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1987,6 +1987,17 @@ pub enum UnknownPrefixSugg {
         style = "verbose"
     )]
     Whitespace(#[primary_span] Span),
+    #[multipart_suggestion(
+        parse_suggestion_str,
+        applicability = "maybe-incorrect",
+        style = "verbose"
+    )]
+    MeantStr {
+        #[suggestion_part(code = "\"")]
+        start: Span,
+        #[suggestion_part(code = "\"")]
+        end: Span,
+    },
 }
 
 #[derive(Diagnostic)]
@@ -2198,12 +2209,21 @@ pub enum MoreThanOneCharSugg {
         ch: String,
     },
     #[suggestion(parse_use_double_quotes, code = "{sugg}", applicability = "machine-applicable")]
-    Quotes {
+    QuotesFull {
         #[primary_span]
         span: Span,
         is_byte: bool,
         sugg: String,
     },
+    #[multipart_suggestion(parse_use_double_quotes, applicability = "machine-applicable")]
+    Quotes {
+        #[suggestion_part(code = "{prefix}\"")]
+        start: Span,
+        #[suggestion_part(code = "\"")]
+        end: Span,
+        is_byte: bool,
+        prefix: &'static str,
+    },
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f57945a52df..63b2b47630b 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -63,6 +63,7 @@ pub(crate) fn parse_token_trees<'psess, 'src>(
         cursor,
         override_span,
         nbsp_is_whitespace: false,
+        last_lifetime: None,
     };
     let (stream, res, unmatched_delims) =
         tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
@@ -105,6 +106,10 @@ struct StringReader<'psess, 'src> {
     /// in this file, it's safe to treat further occurrences of the non-breaking
     /// space character as whitespace.
     nbsp_is_whitespace: bool,
+
+    /// Track the `Span` for the leading `'` of the last lifetime. Used for
+    /// diagnostics to detect possible typo where `"` was meant.
+    last_lifetime: Option<Span>,
 }
 
 impl<'psess, 'src> StringReader<'psess, 'src> {
@@ -130,6 +135,18 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
 
             debug!("next_token: {:?}({:?})", token.kind, self.str_from(start));
 
+            if let rustc_lexer::TokenKind::Semi
+            | rustc_lexer::TokenKind::LineComment { .. }
+            | rustc_lexer::TokenKind::BlockComment { .. }
+            | rustc_lexer::TokenKind::CloseParen
+            | rustc_lexer::TokenKind::CloseBrace
+            | rustc_lexer::TokenKind::CloseBracket = token.kind
+            {
+                // Heuristic: we assume that it is unlikely we're dealing with an unterminated
+                // string surrounded by single quotes.
+                self.last_lifetime = None;
+            }
+
             // Now "cook" the token, converting the simple `rustc_lexer::TokenKind` enum into a
             // rich `rustc_ast::TokenKind`. This turns strings into interned symbols and runs
             // additional validation.
@@ -247,6 +264,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
                     // expansion purposes. See #12512 for the gory details of why
                     // this is necessary.
                     let lifetime_name = self.str_from(start);
+                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
                     if starts_with_number {
                         let span = self.mk_sp(start, self.pos);
                         self.dcx().struct_err("lifetimes cannot start with a number")
@@ -395,10 +413,21 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
         match kind {
             rustc_lexer::LiteralKind::Char { terminated } => {
                 if !terminated {
-                    self.dcx()
+                    let mut err = self
+                        .dcx()
                         .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
-                        .with_code(E0762)
-                        .emit()
+                        .with_code(E0762);
+                    if let Some(lt_sp) = self.last_lifetime {
+                        err.multipart_suggestion(
+                            "if you meant to write a string literal, use double quotes",
+                            vec![
+                                (lt_sp, "\"".to_string()),
+                                (self.mk_sp(start, start + BytePos(1)), "\"".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    err.emit()
                 }
                 self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' '
             }
@@ -669,15 +698,33 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
         let expn_data = prefix_span.ctxt().outer_expn_data();
 
         if expn_data.edition >= Edition::Edition2021 {
+            let mut silence = false;
             // In Rust 2021, this is a hard error.
             let sugg = if prefix == "rb" {
                 Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
             } else if expn_data.is_root() {
-                Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
+                if self.cursor.first() == '\''
+                    && let Some(start) = self.last_lifetime
+                    && self.cursor.third() != '\''
+                {
+                    // An "unclosed `char`" error will be emitted already, silence redundant error.
+                    silence = true;
+                    Some(errors::UnknownPrefixSugg::MeantStr {
+                        start,
+                        end: self.mk_sp(self.pos, self.pos + BytePos(1)),
+                    })
+                } else {
+                    Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
+                }
             } else {
                 None
             };
-            self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
+            let err = errors::UnknownPrefix { span: prefix_span, prefix, sugg };
+            if silence {
+                self.dcx().create_err(err).delay_as_bug();
+            } else {
+                self.dcx().emit_err(err);
+            }
         } else {
             // Before Rust 2021, only emit a lint for migration.
             self.psess.buffer_lint_with_diagnostic(
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 3ebad6a9fd7..fa242a32a18 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -95,11 +95,21 @@ pub(crate) fn emit_unescape_error(
                     }
                     escaped.push(c);
                 }
-                let sugg = format!("{prefix}\"{escaped}\"");
-                MoreThanOneCharSugg::Quotes {
-                    span: full_lit_span,
-                    is_byte: mode == Mode::Byte,
-                    sugg,
+                if escaped.len() != lit.len() || full_lit_span.is_empty() {
+                    let sugg = format!("{prefix}\"{escaped}\"");
+                    MoreThanOneCharSugg::QuotesFull {
+                        span: full_lit_span,
+                        is_byte: mode == Mode::Byte,
+                        sugg,
+                    }
+                } else {
+                    MoreThanOneCharSugg::Quotes {
+                        start: full_lit_span
+                            .with_hi(full_lit_span.lo() + BytePos((prefix.len() + 1) as u32)),
+                        end: full_lit_span.with_lo(full_lit_span.hi() - BytePos(1)),
+                        is_byte: mode == Mode::Byte,
+                        prefix,
+                    }
                 }
             });
             dcx.emit_err(UnescapeError::MoreThanOneChar {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 76e387d54d8..dec31548fc8 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1165,14 +1165,6 @@ extern "rust-intrinsic" {
     /// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
     /// unsafe**. `transmute` should be the absolute last resort.
     ///
-    /// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub],
-    /// unless the pointer was originally created *from* an integer.
-    /// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling],
-    /// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.)
-    /// Any attempt to use the resulting value for integer operations will abort const-evaluation.
-    /// (And even outside `const`, such transmutation is touching on many unspecified aspects of the
-    /// Rust memory model and should be avoided. See below for alternatives.)
-    ///
     /// Because `transmute` is a by-value operation, alignment of the *transmuted values
     /// themselves* is not a concern. As with any other function, the compiler already ensures
     /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
@@ -1183,6 +1175,39 @@ extern "rust-intrinsic" {
     ///
     /// [ub]: ../../reference/behavior-considered-undefined.html
     ///
+    /// # Transmutation between pointers and integers
+    ///
+    /// Special care has to be taken when transmuting between pointers and integers, e.g.
+    /// transmuting between `*const ()` and `usize`.
+    ///
+    /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless
+    /// the pointer was originally created *from* an integer. (That includes this function
+    /// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling],
+    /// but also semantically-equivalent conversions such as punning through `repr(C)` union
+    /// fields.) Any attempt to use the resulting value for integer operations will abort
+    /// const-evaluation. (And even outside `const`, such transmutation is touching on many
+    /// unspecified aspects of the Rust memory model and should be avoided. See below for
+    /// alternatives.)
+    ///
+    /// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not*
+    /// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed
+    /// this way is currently considered undefined behavior.
+    ///
+    /// All this also applies when the integer is nested inside an array, tuple, struct, or enum.
+    /// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this
+    /// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling
+    /// `assume_init()` on that result is considered as completing the pointer-to-integer transmute
+    /// and thus runs into the issues discussed above.
+    ///
+    /// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a
+    /// lossless process. If you want to round-trip a pointer through an integer in a way that you
+    /// can get back the original pointer, you need to use `as` casts, or replace the integer type
+    /// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to
+    /// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized
+    /// memory due to padding). If you specifically need to store something that is "either an
+    /// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without
+    /// any loss (via `as` casts or via `transmute`).
+    ///
     /// # Examples
     ///
     /// There are a few things that `transmute` is really useful for.
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 9e8dac88816..a8940d9cd1e 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -132,11 +132,11 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
 #[rustc_const_unstable(feature = "panic_internals", issue = "none")]
 #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
 pub const fn panic(expr: &'static str) -> ! {
-    // Use Arguments::new_v1 instead of format_args!("{expr}") to potentially
+    // Use Arguments::new_const instead of format_args!("{expr}") to potentially
     // reduce size overhead. The format_args! macro uses str's Display trait to
     // write expr, which calls Formatter::pad, which must accommodate string
     // truncation and padding (even though none is used here). Using
-    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
+    // Arguments::new_const may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
     panic_fmt(fmt::Arguments::new_const(&[expr]));
 }
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index c6eb7be08cd..211921715b0 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -20,9 +20,9 @@ use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
 use rustc_target::spec::{Target, TargetTriple};
-use tempfile::Builder as TempFileBuilder;
 
 use std::env;
+use std::fs::File;
 use std::io::{self, Write};
 use std::panic;
 use std::path::{Path, PathBuf};
@@ -31,6 +31,8 @@ use std::str;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::{Arc, Mutex};
 
+use tempfile::{Builder as TempFileBuilder, TempDir};
+
 use crate::clean::{types::AttributesExt, Attributes};
 use crate::config::Options as RustdocOptions;
 use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
@@ -48,7 +50,55 @@ pub(crate) struct GlobalTestOptions {
     pub(crate) attrs: Vec<String>,
 }
 
-pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
+pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
+    let mut file = File::create(file_path)
+        .map_err(|error| format!("failed to create args file: {error:?}"))?;
+
+    // We now put the common arguments into the file we created.
+    let mut content = vec!["--crate-type=bin".to_string()];
+
+    for cfg in &options.cfgs {
+        content.push(format!("--cfg={cfg}"));
+    }
+    if !options.check_cfgs.is_empty() {
+        content.push("-Zunstable-options".to_string());
+        for check_cfg in &options.check_cfgs {
+            content.push(format!("--check-cfg={check_cfg}"));
+        }
+    }
+
+    if let Some(sysroot) = &options.maybe_sysroot {
+        content.push(format!("--sysroot={}", sysroot.display()));
+    }
+    for lib_str in &options.lib_strs {
+        content.push(format!("-L{lib_str}"));
+    }
+    for extern_str in &options.extern_strs {
+        content.push(format!("--extern={extern_str}"));
+    }
+    content.push("-Ccodegen-units=1".to_string());
+    for codegen_options_str in &options.codegen_options_strs {
+        content.push(format!("-C{codegen_options_str}"));
+    }
+    for unstable_option_str in &options.unstable_opts_strs {
+        content.push(format!("-Z{unstable_option_str}"));
+    }
+
+    let content = content.join("\n");
+
+    file.write(content.as_bytes())
+        .map_err(|error| format!("failed to write arguments to temporary file: {error:?}"))?;
+    Ok(())
+}
+
+fn get_doctest_dir() -> io::Result<TempDir> {
+    TempFileBuilder::new().prefix("rustdoctest").tempdir()
+}
+
+pub(crate) fn run(
+    dcx: &rustc_errors::DiagCtxt,
+    options: RustdocOptions,
+) -> Result<(), ErrorGuaranteed> {
     let input = config::Input::File(options.input.clone());
 
     let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
@@ -118,6 +168,15 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
 
+    let temp_dir = match get_doctest_dir()
+        .map_err(|error| format!("failed to create temporary directory: {error:?}"))
+    {
+        Ok(temp_dir) => temp_dir,
+        Err(error) => return crate::wrap_return(dcx, Err(error)),
+    };
+    let file_path = temp_dir.path().join("rustdoc-cfgs");
+    crate::wrap_return(dcx, generate_args_file(&file_path, &options))?;
+
     let (tests, unused_extern_reports, compiling_test_count) =
         interface::run_compiler(config, |compiler| {
             compiler.enter(|queries| {
@@ -134,6 +193,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
                         Some(compiler.sess.psess.clone_source_map()),
                         None,
                         enable_per_target_ignores,
+                        file_path,
                     );
 
                     let mut hir_collector = HirCollector {
@@ -322,44 +382,35 @@ fn run_test(
     test: &str,
     crate_name: &str,
     line: usize,
-    rustdoc_options: RustdocOptions,
+    rustdoc_options: IndividualTestOptions,
     mut lang_string: LangString,
     no_run: bool,
-    runtool: Option<String>,
-    runtool_args: Vec<String>,
-    target: TargetTriple,
     opts: &GlobalTestOptions,
     edition: Edition,
-    outdir: DirState,
     path: PathBuf,
-    test_id: &str,
     report_unused_externs: impl Fn(UnusedExterns),
 ) -> Result<(), TestFailure> {
-    let (test, line_offset, supports_color) =
-        make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
+    let (test, line_offset, supports_color) = make_test(
+        test,
+        Some(crate_name),
+        lang_string.test_harness,
+        opts,
+        edition,
+        Some(&rustdoc_options.test_id),
+    );
 
     // Make sure we emit well-formed executable names for our target.
-    let rust_out = add_exe_suffix("rust_out".to_owned(), &target);
-    let output_file = outdir.path().join(rust_out);
+    let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
+    let output_file = rustdoc_options.outdir.path().join(rust_out);
 
     let rustc_binary = rustdoc_options
         .test_builder
         .as_deref()
         .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
     let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
-    compiler.arg("--crate-type").arg("bin");
-    for cfg in &rustdoc_options.cfgs {
-        compiler.arg("--cfg").arg(&cfg);
-    }
-    if !rustdoc_options.check_cfgs.is_empty() {
-        compiler.arg("-Z").arg("unstable-options");
-        for check_cfg in &rustdoc_options.check_cfgs {
-            compiler.arg("--check-cfg").arg(&check_cfg);
-        }
-    }
-    if let Some(sysroot) = rustdoc_options.maybe_sysroot {
-        compiler.arg("--sysroot").arg(sysroot);
-    }
+
+    compiler.arg(&format!("@{}", rustdoc_options.arg_file.display()));
+
     compiler.arg("--edition").arg(&edition.to_string());
     compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
     compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
@@ -367,29 +418,17 @@ fn run_test(
     if lang_string.test_harness {
         compiler.arg("--test");
     }
-    if rustdoc_options.json_unused_externs.is_enabled() && !lang_string.compile_fail {
+    if rustdoc_options.is_json_unused_externs_enabled && !lang_string.compile_fail {
         compiler.arg("--error-format=json");
         compiler.arg("--json").arg("unused-externs");
-        compiler.arg("-Z").arg("unstable-options");
         compiler.arg("-W").arg("unused_crate_dependencies");
+        compiler.arg("-Z").arg("unstable-options");
     }
-    for lib_str in &rustdoc_options.lib_strs {
-        compiler.arg("-L").arg(&lib_str);
-    }
-    for extern_str in &rustdoc_options.extern_strs {
-        compiler.arg("--extern").arg(&extern_str);
-    }
-    compiler.arg("-Ccodegen-units=1");
-    for codegen_options_str in &rustdoc_options.codegen_options_strs {
-        compiler.arg("-C").arg(&codegen_options_str);
-    }
-    for unstable_option_str in &rustdoc_options.unstable_opts_strs {
-        compiler.arg("-Z").arg(&unstable_option_str);
-    }
-    if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
+
+    if no_run && !lang_string.compile_fail && rustdoc_options.should_persist_doctests {
         compiler.arg("--emit=metadata");
     }
-    compiler.arg("--target").arg(match target {
+    compiler.arg("--target").arg(match rustdoc_options.target {
         TargetTriple::TargetTriple(s) => s,
         TargetTriple::TargetJson { path_for_rustdoc, .. } => {
             path_for_rustdoc.to_str().expect("target path must be valid unicode").to_string()
@@ -485,10 +524,10 @@ fn run_test(
     let mut cmd;
 
     let output_file = make_maybe_absolute_path(output_file);
-    if let Some(tool) = runtool {
+    if let Some(tool) = rustdoc_options.runtool {
         let tool = make_maybe_absolute_path(tool.into());
         cmd = Command::new(tool);
-        cmd.args(runtool_args);
+        cmd.args(rustdoc_options.runtool_args);
         cmd.arg(output_file);
     } else {
         cmd = Command::new(output_file);
@@ -897,6 +936,56 @@ fn partition_source(s: &str, edition: Edition) -> (String, String, String) {
     (before, after, crates)
 }
 
+pub(crate) struct IndividualTestOptions {
+    test_builder: Option<PathBuf>,
+    test_builder_wrappers: Vec<PathBuf>,
+    is_json_unused_externs_enabled: bool,
+    should_persist_doctests: bool,
+    error_format: ErrorOutputType,
+    test_run_directory: Option<PathBuf>,
+    nocapture: bool,
+    arg_file: PathBuf,
+    outdir: DirState,
+    runtool: Option<String>,
+    runtool_args: Vec<String>,
+    target: TargetTriple,
+    test_id: String,
+}
+
+impl IndividualTestOptions {
+    fn new(options: &RustdocOptions, arg_file: &Path, test_id: String) -> Self {
+        let outdir = if let Some(ref path) = options.persist_doctests {
+            let mut path = path.clone();
+            path.push(&test_id);
+
+            if let Err(err) = std::fs::create_dir_all(&path) {
+                eprintln!("Couldn't create directory for doctest executables: {err}");
+                panic::resume_unwind(Box::new(()));
+            }
+
+            DirState::Perm(path)
+        } else {
+            DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir"))
+        };
+
+        Self {
+            test_builder: options.test_builder.clone(),
+            test_builder_wrappers: options.test_builder_wrappers.clone(),
+            is_json_unused_externs_enabled: options.json_unused_externs.is_enabled(),
+            should_persist_doctests: options.persist_doctests.is_none(),
+            error_format: options.error_format,
+            test_run_directory: options.test_run_directory.clone(),
+            nocapture: options.nocapture,
+            arg_file: arg_file.into(),
+            outdir,
+            runtool: options.runtool.clone(),
+            runtool_args: options.runtool_args.clone(),
+            target: options.target.clone(),
+            test_id,
+        }
+    }
+}
+
 pub(crate) trait Tester {
     fn add_test(&mut self, test: String, config: LangString, line: usize);
     fn get_line(&self) -> usize {
@@ -941,6 +1030,7 @@ pub(crate) struct Collector {
     visited_tests: FxHashMap<(String, usize), usize>,
     unused_extern_reports: Arc<Mutex<Vec<UnusedExterns>>>,
     compiling_test_count: AtomicUsize,
+    arg_file: PathBuf,
 }
 
 impl Collector {
@@ -952,6 +1042,7 @@ impl Collector {
         source_map: Option<Lrc<SourceMap>>,
         filename: Option<PathBuf>,
         enable_per_target_ignores: bool,
+        arg_file: PathBuf,
     ) -> Collector {
         Collector {
             tests: Vec::new(),
@@ -967,6 +1058,7 @@ impl Collector {
             visited_tests: FxHashMap::default(),
             unused_extern_reports: Default::default(),
             compiling_test_count: AtomicUsize::new(0),
+            arg_file,
         }
     }
 
@@ -1009,13 +1101,9 @@ impl Tester for Collector {
         let crate_name = self.crate_name.clone();
         let opts = self.opts.clone();
         let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
-        let rustdoc_options = self.rustdoc_options.clone();
-        let runtool = self.rustdoc_options.runtool.clone();
-        let runtool_args = self.rustdoc_options.runtool_args.clone();
-        let target = self.rustdoc_options.target.clone();
-        let target_str = target.to_string();
+        let target_str = self.rustdoc_options.target.to_string();
         let unused_externs = self.unused_extern_reports.clone();
-        let no_run = config.no_run || rustdoc_options.no_run;
+        let no_run = config.no_run || self.rustdoc_options.no_run;
         if !config.compile_fail {
             self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
         }
@@ -1049,23 +1137,9 @@ impl Tester for Collector {
                 self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
             },
         );
-        let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() {
-            path.push(&test_id);
 
-            if let Err(err) = std::fs::create_dir_all(&path) {
-                eprintln!("Couldn't create directory for doctest executables: {err}");
-                panic::resume_unwind(Box::new(()));
-            }
-
-            DirState::Perm(path)
-        } else {
-            DirState::Temp(
-                TempFileBuilder::new()
-                    .prefix("rustdoctest")
-                    .tempdir()
-                    .expect("rustdoc needs a tempdir"),
-            )
-        };
+        let rustdoc_test_options =
+            IndividualTestOptions::new(&self.rustdoc_options, &self.arg_file, test_id);
 
         debug!("creating test {name}: {test}");
         self.tests.push(test::TestDescAndFn {
@@ -1096,17 +1170,12 @@ impl Tester for Collector {
                     &test,
                     &crate_name,
                     line,
-                    rustdoc_options,
+                    rustdoc_test_options,
                     config,
                     no_run,
-                    runtool,
-                    runtool_args,
-                    target,
                     &opts,
                     edition,
-                    outdir,
                     path,
-                    &test_id,
                     report_unused_externs,
                 );
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 18651875130..b78fb4c4eee 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -664,7 +664,7 @@ fn usage(argv0: &str) {
 /// A result type used by several functions under `main()`.
 type MainResult = Result<(), ErrorGuaranteed>;
 
-fn wrap_return(dcx: &rustc_errors::DiagCtxt, res: Result<(), String>) -> MainResult {
+pub(crate) fn wrap_return(dcx: &rustc_errors::DiagCtxt, res: Result<(), String>) -> MainResult {
     match res {
         Ok(()) => dcx.has_errors().map_or(Ok(()), Err),
         Err(err) => Err(dcx.err(err)),
@@ -731,7 +731,7 @@ fn main_args(
 
     match (options.should_test, options.markdown_input()) {
         (true, true) => return wrap_return(&diag, markdown::test(options)),
-        (true, false) => return doctest::run(options),
+        (true, false) => return doctest::run(&diag, options),
         (false, true) => {
             let input = options.input.clone();
             let edition = options.edition;
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index b661ced0169..dcd2cf02a30 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -3,11 +3,13 @@ use std::fs::{create_dir_all, read_to_string, File};
 use std::io::prelude::*;
 use std::path::Path;
 
+use tempfile::tempdir;
+
 use rustc_span::edition::Edition;
 use rustc_span::DUMMY_SP;
 
 use crate::config::{Options, RenderOptions};
-use crate::doctest::{Collector, GlobalTestOptions};
+use crate::doctest::{generate_args_file, Collector, GlobalTestOptions};
 use crate::html::escape::Escape;
 use crate::html::markdown;
 use crate::html::markdown::{
@@ -146,6 +148,12 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
         .map_err(|err| format!("{input}: {err}", input = options.input.display()))?;
     let mut opts = GlobalTestOptions::default();
     opts.no_crate_inject = true;
+
+    let temp_dir =
+        tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
+    let file_path = temp_dir.path().join("rustdoc-cfgs");
+    generate_args_file(&file_path, &options)?;
+
     let mut collector = Collector::new(
         options.input.display().to_string(),
         options.clone(),
@@ -154,6 +162,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
         None,
         Some(options.input),
         options.enable_per_target_ignores,
+        file_path,
     );
     collector.set_position(DUMMY_SP);
     let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index e5e7b559c92..419b04231b5 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -9,8 +9,8 @@ pub fn out_dir() -> PathBuf {
     env::var_os("TMPDIR").unwrap().into()
 }
 
-fn setup_common_build_cmd() -> Command {
-    let rustc = env::var("RUSTC").unwrap();
+fn setup_common_build_cmd(command: &str) -> Command {
+    let rustc = env::var(command).unwrap();
     let mut cmd = Command::new(rustc);
     cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir());
     cmd
@@ -33,6 +33,10 @@ pub fn aux_build() -> AuxBuildInvocationBuilder {
     AuxBuildInvocationBuilder::new()
 }
 
+pub fn rustdoc() -> Rustdoc {
+    Rustdoc::new()
+}
+
 #[derive(Debug)]
 pub struct RustcInvocationBuilder {
     cmd: Command,
@@ -40,7 +44,7 @@ pub struct RustcInvocationBuilder {
 
 impl RustcInvocationBuilder {
     fn new() -> Self {
-        let cmd = setup_common_build_cmd();
+        let cmd = setup_common_build_cmd("RUSTC");
         Self { cmd }
     }
 
@@ -74,7 +78,7 @@ pub struct AuxBuildInvocationBuilder {
 
 impl AuxBuildInvocationBuilder {
     fn new() -> Self {
-        let mut cmd = setup_common_build_cmd();
+        let mut cmd = setup_common_build_cmd("RUSTC");
         cmd.arg("--crate-type=lib");
         Self { cmd }
     }
@@ -97,6 +101,35 @@ impl AuxBuildInvocationBuilder {
     }
 }
 
+#[derive(Debug)]
+pub struct Rustdoc {
+    cmd: Command,
+}
+
+impl Rustdoc {
+    fn new() -> Self {
+        let cmd = setup_common_build_cmd("RUSTDOC");
+        Self { cmd }
+    }
+
+    pub fn arg(&mut self, arg: &str) -> &mut Self {
+        self.cmd.arg(arg);
+        self
+    }
+
+    #[track_caller]
+    pub fn run(&mut self) -> Output {
+        let caller_location = std::panic::Location::caller();
+        let caller_line_number = caller_location.line();
+
+        let output = self.cmd.output().unwrap();
+        if !output.status.success() {
+            handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
+        }
+        output
+    }
+}
+
 fn run_common(bin_name: &str) -> (Command, Output) {
     let target = env::var("TARGET").unwrap();
 
diff --git a/tests/mir-opt/inline_coroutine_body.rs b/tests/mir-opt/inline_coroutine_body.rs
new file mode 100644
index 00000000000..be73bc49de5
--- /dev/null
+++ b/tests/mir-opt/inline_coroutine_body.rs
@@ -0,0 +1,28 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// skip-filecheck
+//@ unit-test: Inline
+//@ edition: 2021
+//@ compile-flags: -Zinline-mir-hint-threshold=10000 -Zinline-mir-threshold=10000 --crate-type=lib
+
+pub async fn run(permit: ActionPermit<'_, ()>, ctx: &mut core::task::Context<'_>) {
+    run2(permit, ctx);
+}
+
+// EMIT_MIR inline_coroutine_body.run2-{closure#0}.Inline.diff
+fn run2<T>(permit: ActionPermit<'_, T>, ctx: &mut core::task::Context) {
+    _ = || {
+        let mut fut = ActionPermit::perform(permit);
+        let fut = unsafe { core::pin::Pin::new_unchecked(&mut fut) };
+        _ = core::future::Future::poll(fut, ctx);
+    };
+}
+
+pub struct ActionPermit<'a, T> {
+    _guard: core::cell::Ref<'a, T>,
+}
+
+impl<'a, T> ActionPermit<'a, T> {
+    async fn perform(self) {
+        core::future::ready(()).await
+    }
+}
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
new file mode 100644
index 00000000000..b189b4e73f4
--- /dev/null
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff
@@ -0,0 +1,281 @@
+- // MIR for `run2::{closure#0}` before Inline
++ // MIR for `run2::{closure#0}` after Inline
+  
+  fn run2::{closure#0}(_1: {closure@$DIR/inline_coroutine_body.rs:13:9: 13:11}) -> () {
+      debug permit => (_1.0: ActionPermit<'_, T>);
+      debug ctx => (*(_1.1: &mut std::task::Context<'_>));
+      let mut _0: ();
+      let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _3: ActionPermit<'_, T>;
+      let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let _6: ();
+      let mut _7: std::task::Poll<()>;
+      let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+      let mut _9: &mut std::task::Context<'_>;
+      let mut _10: &mut std::task::Context<'_>;
+      scope 1 {
+          debug fut => _2;
+          let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+          scope 2 {
+              debug fut => _4;
+              scope 4 {
+              }
++             scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
++                 debug _task_context => _31;
++                 debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
++                 let _11: ActionPermit<'_, T>;
++                 let mut _12: std::future::Ready<()>;
++                 let mut _13: std::future::Ready<()>;
++                 let mut _14: ();
++                 let mut _16: ();
++                 let _17: ();
++                 let mut _18: std::task::Poll<()>;
++                 let mut _19: std::pin::Pin<&mut std::future::Ready<()>>;
++                 let mut _20: &mut std::future::Ready<()>;
++                 let mut _21: &mut std::future::Ready<()>;
++                 let mut _22: &mut std::task::Context<'_>;
++                 let mut _23: &mut std::task::Context<'_>;
++                 let mut _24: &mut std::task::Context<'_>;
++                 let mut _25: isize;
++                 let mut _27: !;
++                 let mut _28: &mut std::task::Context<'_>;
++                 let mut _29: ();
++                 let mut _30: ();
++                 let mut _31: &mut std::task::Context<'_>;
++                 let mut _32: u32;
++                 let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 scope 8 {
++                     debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
++                     let mut _15: std::future::Ready<()>;
++                     scope 9 {
++                         debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
++                         let _26: ();
++                         scope 10 {
++                         }
++                         scope 11 {
++                             debug result => _26;
++                         }
++                     }
++                     scope 12 (inlined ready::<()>) {
++                         debug t => _14;
++                         let mut _41: std::option::Option<()>;
++                     }
++                 }
++             }
+          }
+          scope 3 {
++             scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
++                 debug pointer => _5;
++             }
+          }
+      }
++     scope 5 (inlined ActionPermit::<'_, T>::perform) {
++         debug self => _3;
++     }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = move (_1.0: ActionPermit<'_, T>);
+-         _2 = ActionPermit::<'_, T>::perform(move _3) -> [return: bb1, unwind unreachable];
+-     }
+- 
+-     bb1: {
++         _2 = {coroutine@$DIR/inline_coroutine_body.rs:25:28: 27:6 (#0)} { self: move _3 };
+          StorageDead(_3);
+          StorageLive(_4);
+          StorageLive(_5);
+          _5 = &mut _2;
+-         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
+-     }
+- 
+-     bb2: {
++         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
+          StorageDead(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          StorageLive(_8);
+          _8 = move _4;
+          StorageLive(_9);
+          _10 = deref_copy (_1.1: &mut std::task::Context<'_>);
+          _9 = &mut (*_10);
+-         _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
++         StorageLive(_11);
++         StorageLive(_15);
++         StorageLive(_16);
++         StorageLive(_25);
++         StorageLive(_27);
++         StorageLive(_30);
++         StorageLive(_31);
++         StorageLive(_32);
++         StorageLive(_33);
++         StorageLive(_34);
++         StorageLive(_35);
++         StorageLive(_36);
++         StorageLive(_37);
++         StorageLive(_38);
++         StorageLive(_39);
++         StorageLive(_40);
++         _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _32 = discriminant((*_33));
++         switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8];
+      }
+  
+-     bb3: {
++     bb1: {
++         StorageDead(_2);
++         return;
++     }
++ 
++     bb2: {
++         StorageDead(_40);
++         StorageDead(_39);
++         StorageDead(_38);
++         StorageDead(_37);
++         StorageDead(_36);
++         StorageDead(_35);
++         StorageDead(_34);
++         StorageDead(_33);
++         StorageDead(_32);
++         StorageDead(_31);
++         StorageDead(_30);
++         StorageDead(_27);
++         StorageDead(_25);
++         StorageDead(_16);
++         StorageDead(_15);
++         StorageDead(_11);
+          StorageDead(_9);
+          StorageDead(_8);
+          StorageDead(_7);
+          _6 = const ();
+          StorageDead(_6);
+          _0 = const ();
+          StorageDead(_4);
+-         drop(_2) -> [return: bb4, unwind unreachable];
++         drop(_2) -> [return: bb1, unwind unreachable];
+      }
+  
++     bb3: {
++         _31 = move _9;
++         _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         StorageLive(_12);
++         StorageLive(_13);
++         StorageLive(_14);
++         _14 = ();
++         StorageLive(_41);
++         _41 = Option::<()>::Some(_14);
++         _13 = std::future::Ready::<()>(move _41);
++         StorageDead(_41);
++         StorageDead(_14);
++         _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb4, unwind unreachable];
++     }
++ 
+      bb4: {
+-         StorageDead(_2);
+-         return;
++         StorageDead(_13);
++         _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         goto -> bb5;
++     }
++ 
++     bb5: {
++         StorageLive(_17);
++         StorageLive(_18);
++         StorageLive(_19);
++         StorageLive(_20);
++         StorageLive(_21);
++         _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _20 = &mut (*_21);
++         _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable];
++     }
++ 
++     bb6: {
++         StorageDead(_20);
++         StorageLive(_22);
++         StorageLive(_23);
++         StorageLive(_24);
++         _24 = _31;
++         _23 = move _24;
++         _22 = &mut (*_23);
++         StorageDead(_24);
++         _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb7, unwind unreachable];
++     }
++ 
++     bb7: {
++         StorageDead(_22);
++         StorageDead(_19);
++         _25 = discriminant(_18);
++         switchInt(move _25) -> [0: bb10, 1: bb9, otherwise: bb8];
++     }
++ 
++     bb8: {
++         unreachable;
++     }
++ 
++     bb9: {
++         _17 = const ();
++         StorageDead(_23);
++         StorageDead(_21);
++         StorageDead(_18);
++         StorageDead(_17);
++         StorageLive(_28);
++         StorageLive(_29);
++         _29 = ();
++         _7 = Poll::<()>::Pending;
++         StorageDead(_12);
++         StorageDead(_28);
++         StorageDead(_29);
++         _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         discriminant((*_38)) = 3;
++         goto -> bb2;
++     }
++ 
++     bb10: {
++         StorageLive(_26);
++         _26 = ((_18 as Ready).0: ());
++         _30 = _26;
++         StorageDead(_26);
++         StorageDead(_23);
++         StorageDead(_21);
++         StorageDead(_18);
++         StorageDead(_17);
++         StorageDead(_12);
++         _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable];
++     }
++ 
++     bb11: {
++         _7 = Poll::<()>::Ready(move _30);
++         _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         discriminant((*_40)) = 1;
++         goto -> bb2;
++     }
++ 
++     bb12: {
++         StorageLive(_12);
++         StorageLive(_28);
++         StorageLive(_29);
++         _28 = move _9;
++         StorageDead(_29);
++         _31 = move _28;
++         StorageDead(_28);
++         _16 = const ();
++         goto -> bb5;
++     }
++ 
++     bb13: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb13, unwind unreachable];
+      }
+  }
+  
diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
new file mode 100644
index 00000000000..ed18c0a3adb
--- /dev/null
+++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff
@@ -0,0 +1,341 @@
+- // MIR for `run2::{closure#0}` before Inline
++ // MIR for `run2::{closure#0}` after Inline
+  
+  fn run2::{closure#0}(_1: {closure@$DIR/inline_coroutine_body.rs:13:9: 13:11}) -> () {
+      debug permit => (_1.0: ActionPermit<'_, T>);
+      debug ctx => (*(_1.1: &mut std::task::Context<'_>));
+      let mut _0: ();
+      let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let mut _3: ActionPermit<'_, T>;
+      let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
+      let _6: ();
+      let mut _7: std::task::Poll<()>;
+      let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+      let mut _9: &mut std::task::Context<'_>;
+      let mut _10: &mut std::task::Context<'_>;
+      scope 1 {
+          debug fut => _2;
+          let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
+          scope 2 {
+              debug fut => _4;
+              scope 4 {
+              }
++             scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
++                 debug _task_context => _31;
++                 debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
++                 let _11: ActionPermit<'_, T>;
++                 let mut _12: std::future::Ready<()>;
++                 let mut _13: std::future::Ready<()>;
++                 let mut _14: ();
++                 let mut _16: ();
++                 let _17: ();
++                 let mut _18: std::task::Poll<()>;
++                 let mut _19: std::pin::Pin<&mut std::future::Ready<()>>;
++                 let mut _20: &mut std::future::Ready<()>;
++                 let mut _21: &mut std::future::Ready<()>;
++                 let mut _22: &mut std::task::Context<'_>;
++                 let mut _23: &mut std::task::Context<'_>;
++                 let mut _24: &mut std::task::Context<'_>;
++                 let mut _25: isize;
++                 let mut _27: !;
++                 let mut _28: &mut std::task::Context<'_>;
++                 let mut _29: ();
++                 let mut _30: ();
++                 let mut _31: &mut std::task::Context<'_>;
++                 let mut _32: u32;
++                 let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _41: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 let mut _42: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
++                 scope 8 {
++                     debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
++                     let mut _15: std::future::Ready<()>;
++                     scope 9 {
++                         debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
++                         let _26: ();
++                         scope 10 {
++                         }
++                         scope 11 {
++                             debug result => _26;
++                         }
++                     }
++                     scope 12 (inlined ready::<()>) {
++                         debug t => _14;
++                         let mut _43: std::option::Option<()>;
++                     }
++                 }
++             }
+          }
+          scope 3 {
++             scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
++                 debug pointer => _5;
++             }
+          }
+      }
++     scope 5 (inlined ActionPermit::<'_, T>::perform) {
++         debug self => _3;
++     }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _3 = move (_1.0: ActionPermit<'_, T>);
+-         _2 = ActionPermit::<'_, T>::perform(move _3) -> [return: bb1, unwind: bb6];
+-     }
+- 
+-     bb1: {
++         _2 = {coroutine@$DIR/inline_coroutine_body.rs:25:28: 27:6 (#0)} { self: move _3 };
+          StorageDead(_3);
+          StorageLive(_4);
+          StorageLive(_5);
+          _5 = &mut _2;
+-         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
+-     }
+- 
+-     bb2: {
++         _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
+          StorageDead(_5);
+          StorageLive(_6);
+          StorageLive(_7);
+          StorageLive(_8);
+          _8 = move _4;
+          StorageLive(_9);
+          _10 = deref_copy (_1.1: &mut std::task::Context<'_>);
+          _9 = &mut (*_10);
+-         _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
++         StorageLive(_11);
++         StorageLive(_15);
++         StorageLive(_16);
++         StorageLive(_25);
++         StorageLive(_27);
++         StorageLive(_30);
++         StorageLive(_31);
++         StorageLive(_32);
++         StorageLive(_33);
++         StorageLive(_34);
++         StorageLive(_35);
++         StorageLive(_36);
++         StorageLive(_37);
++         StorageLive(_38);
++         StorageLive(_39);
++         StorageLive(_40);
++         StorageLive(_41);
++         StorageLive(_42);
++         _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _32 = discriminant((*_33));
++         switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10];
+      }
+  
+-     bb3: {
++     bb1: {
++         StorageDead(_2);
++         return;
++     }
++ 
++     bb2 (cleanup): {
++         drop(_2) -> [return: bb3, unwind terminate(cleanup)];
++     }
++ 
++     bb3 (cleanup): {
++         resume;
++     }
++ 
++     bb4: {
++         StorageDead(_42);
++         StorageDead(_41);
++         StorageDead(_40);
++         StorageDead(_39);
++         StorageDead(_38);
++         StorageDead(_37);
++         StorageDead(_36);
++         StorageDead(_35);
++         StorageDead(_34);
++         StorageDead(_33);
++         StorageDead(_32);
++         StorageDead(_31);
++         StorageDead(_30);
++         StorageDead(_27);
++         StorageDead(_25);
++         StorageDead(_16);
++         StorageDead(_15);
++         StorageDead(_11);
+          StorageDead(_9);
+          StorageDead(_8);
+          StorageDead(_7);
+          _6 = const ();
+          StorageDead(_6);
+          _0 = const ();
+          StorageDead(_4);
+-         drop(_2) -> [return: bb4, unwind: bb6];
++         drop(_2) -> [return: bb1, unwind: bb3];
+      }
+  
+-     bb4: {
+-         StorageDead(_2);
+-         return;
++     bb5: {
++         _31 = move _9;
++         _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
++         StorageLive(_12);
++         StorageLive(_13);
++         StorageLive(_14);
++         _14 = ();
++         StorageLive(_43);
++         _43 = Option::<()>::Some(_14);
++         _13 = std::future::Ready::<()>(move _43);
++         StorageDead(_43);
++         StorageDead(_14);
++         _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb6, unwind: bb17];
+      }
+  
+-     bb5 (cleanup): {
+-         drop(_2) -> [return: bb6, unwind terminate(cleanup)];
++     bb6: {
++         StorageDead(_13);
++         _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
++         goto -> bb7;
+      }
+  
+-     bb6 (cleanup): {
+-         resume;
++     bb7: {
++         StorageLive(_17);
++         StorageLive(_18);
++         StorageLive(_19);
++         StorageLive(_20);
++         StorageLive(_21);
++         _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
++         _20 = &mut (*_21);
++         _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15];
++     }
++ 
++     bb8: {
++         StorageDead(_20);
++         StorageLive(_22);
++         StorageLive(_23);
++         StorageLive(_24);
++         _24 = _31;
++         _23 = move _24;
++         _22 = &mut (*_23);
++         StorageDead(_24);
++         _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb9, unwind: bb14];
++     }
++ 
++     bb9: {
++         StorageDead(_22);
++         StorageDead(_19);
++         _25 = discriminant(_18);
++         switchInt(move _25) -> [0: bb12, 1: bb11, otherwise: bb10];
++     }
++ 
++     bb10: {
++         unreachable;
++     }
++ 
++     bb11: {
++         _17 = const ();
++         StorageDead(_23);
++         StorageDead(_21);
++         StorageDead(_18);
++         StorageDead(_17);
++         StorageLive(_28);
++         StorageLive(_29);
++         _29 = ();
++         _7 = Poll::<()>::Pending;
++         StorageDead(_12);
++         StorageDead(_28);
++         StorageDead(_29);
++         _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         discriminant((*_38)) = 3;
++         goto -> bb4;
++     }
++ 
++     bb12: {
++         StorageLive(_26);
++         _26 = ((_18 as Ready).0: ());
++         _30 = _26;
++         StorageDead(_26);
++         StorageDead(_23);
++         StorageDead(_21);
++         StorageDead(_18);
++         StorageDead(_17);
++         StorageDead(_12);
++         _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19];
++     }
++ 
++     bb13: {
++         _7 = Poll::<()>::Ready(move _30);
++         _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         discriminant((*_40)) = 1;
++         goto -> bb4;
++     }
++ 
++     bb14 (cleanup): {
++         StorageDead(_22);
++         StorageDead(_19);
++         StorageDead(_23);
++         goto -> bb16;
++     }
++ 
++     bb15 (cleanup): {
++         StorageDead(_20);
++         StorageDead(_19);
++         goto -> bb16;
++     }
++ 
++     bb16 (cleanup): {
++         StorageDead(_21);
++         StorageDead(_18);
++         StorageDead(_17);
++         goto -> bb18;
++     }
++ 
++     bb17 (cleanup): {
++         StorageDead(_13);
++         goto -> bb18;
++     }
++ 
++     bb18 (cleanup): {
++         StorageDead(_12);
++         _41 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)];
++     }
++ 
++     bb19 (cleanup): {
++         _42 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
++         discriminant((*_42)) = 2;
++         goto -> bb2;
++     }
++ 
++     bb20: {
++         StorageLive(_12);
++         StorageLive(_28);
++         StorageLive(_29);
++         _28 = move _9;
++         StorageDead(_29);
++         _31 = move _28;
++         StorageDead(_28);
++         _16 = const ();
++         goto -> bb7;
++     }
++ 
++     bb21: {
++         assert(const false, "`async fn` resumed after panicking") -> [success: bb21, unwind: bb2];
++     }
++ 
++     bb22: {
++         assert(const false, "`async fn` resumed after completion") -> [success: bb22, unwind: bb2];
+      }
+  }
+  
diff --git a/tests/run-make/rustdoc-test-args/foo.rs b/tests/run-make/rustdoc-test-args/foo.rs
new file mode 100644
index 00000000000..51d17849fd7
--- /dev/null
+++ b/tests/run-make/rustdoc-test-args/foo.rs
@@ -0,0 +1,3 @@
+//! ```
+//! let x = 12;
+//! ```
diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs
new file mode 100644
index 00000000000..808d13928eb
--- /dev/null
+++ b/tests/run-make/rustdoc-test-args/rmake.rs
@@ -0,0 +1,18 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustdoc};
+use std::{fs, iter};
+use std::path::Path;
+
+fn generate_a_lot_of_cfgs(path: &Path) {
+    let content = iter::repeat("--cfg=a\n").take(100_000).collect::<String>();
+    fs::write(path, content.as_bytes()).expect("failed to create args file");
+}
+
+fn main() {
+    let arg_file = out_dir().join("args");
+    generate_a_lot_of_cfgs(&arg_file);
+
+    let arg_file = format!("@{}", arg_file.display());
+    rustdoc().arg("--test").arg(&arg_file).arg("foo.rs").run();
+}
diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs
new file mode 100644
index 00000000000..b9e729bff62
--- /dev/null
+++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs
@@ -0,0 +1,26 @@
+// issue: rust-lang/rust#104779
+// ICE region infer, IndexMap: key not found
+
+struct Inv<'a>(&'a mut &'a ());
+enum Foo<T> {
+    Bar,
+    Var(T),
+}
+type Subtype = Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>;
+type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
+
+fn foo() -> impl Sized {
+//~^ WARN function cannot return without recursing
+    loop {
+        match foo() {
+        //~^ ERROR higher-ranked subtype error
+        //~^^ ERROR higher-ranked subtype error
+            Subtype::Bar => (),
+            //~^ ERROR higher-ranked subtype error
+            //~^^ ERROR higher-ranked subtype error
+            Supertype::Var(x) => {}
+        }
+    }
+}
+
+pub fn main() {}
diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr
new file mode 100644
index 00000000000..887cb14a769
--- /dev/null
+++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr
@@ -0,0 +1,42 @@
+warning: function cannot return without recursing
+  --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:12:1
+   |
+LL | fn foo() -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+...
+LL |         match foo() {
+   |               ----- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
+error: higher-ranked subtype error
+  --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15
+   |
+LL |         match foo() {
+   |               ^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15
+   |
+LL |         match foo() {
+   |               ^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: higher-ranked subtype error
+  --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13
+   |
+LL |             Subtype::Bar => (),
+   |             ^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13
+   |
+LL |             Subtype::Bar => (),
+   |             ^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
diff --git a/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs b/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs
new file mode 100644
index 00000000000..ed5ba32b621
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/poly-const-uneval-ice-106423.rs
@@ -0,0 +1,57 @@
+// issue: rust-lang/rust#106423
+// ICE collection encountered polymorphic constant: UnevaluatedConst {..}
+//@ edition:2021
+//@ check-pass
+
+#![feature(generic_const_exprs, generic_arg_infer)]
+#![allow(incomplete_features)]
+#![allow(unused)]
+
+use core::mem::MaybeUninit;
+
+pub struct Arr<T, const N: usize> {
+    v: [MaybeUninit<T>; N],
+}
+
+impl<T, const N: usize> Arr<T, N> {
+    const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
+    const INIT: [MaybeUninit<T>; N] = [Self::ELEM; N]; // important for optimization of `new`
+
+    fn new() -> Self {
+        Arr { v: Self::INIT }
+    }
+}
+
+pub struct BaFormatFilter<const N: usize> {}
+
+pub enum DigitalFilter<const N: usize>
+where
+    [(); N * 2 + 1]: Sized,
+    [(); N * 2]: Sized,
+{
+    Ba(BaFormatFilter<{ N * 2 + 1 }>),
+}
+
+pub fn iirfilter_st_copy<const N: usize, const M: usize>(_: [f32; M]) -> DigitalFilter<N>
+where
+    [(); N * 2 + 1]: Sized,
+    [(); N * 2]: Sized,
+{
+    let zpk = zpk2tf_st(&Arr::<f32, { N * 2 }>::new(), &Arr::<f32, { N * 2 }>::new());
+    DigitalFilter::Ba(zpk)
+}
+
+pub fn zpk2tf_st<const N: usize>(
+    _z: &Arr<f32, N>,
+    _p: &Arr<f32, N>,
+) -> BaFormatFilter<{ N + 1 }>
+where
+    [(); N + 1]: Sized,
+{
+    BaFormatFilter {}
+}
+
+
+fn main() {
+    iirfilter_st_copy::<4, 2>([10., 50.,]);
+}
diff --git a/tests/ui/drop/norm-ice-106444.rs b/tests/ui/drop/norm-ice-106444.rs
new file mode 100644
index 00000000000..b248bc73bbe
--- /dev/null
+++ b/tests/ui/drop/norm-ice-106444.rs
@@ -0,0 +1,16 @@
+// issue: rust-lang/rust#106444
+// ICE failed to normalize
+//@ compile-flags: -Zmir-opt-level=3
+//@ check-pass
+
+#![crate_type="lib"]
+
+pub trait A {
+    type B;
+}
+
+pub struct S<T: A>(T::B);
+
+pub fn foo<T: A>(p: *mut S<T>) {
+    unsafe { core::ptr::drop_in_place(p) };
+}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs
new file mode 100644
index 00000000000..8df24702811
--- /dev/null
+++ b/tests/ui/higher-ranked/structually-relate-aliases.rs
@@ -0,0 +1,17 @@
+// regression test for issue #121649.
+
+trait ToUnit<'a> {
+    type Unit;
+}
+
+trait Overlap<T> {}
+
+type Assoc<'a, T> = <T as ToUnit<'a>>::Unit;
+
+impl<T> Overlap<T> for T {}
+
+impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
+//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
+//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
new file mode 100644
index 00000000000..59fab52b221
--- /dev/null
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -0,0 +1,27 @@
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
+WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) }
+error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
+  --> $DIR/structually-relate-aliases.rs:13:36
+   |
+LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
+   |                                    ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
+   |       ++++++++++++++++++++
+
+error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
+  --> $DIR/structually-relate-aliases.rs:13:17
+   |
+LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
+   |       ++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/recursive-ice-101862.rs b/tests/ui/impl-trait/recursive-ice-101862.rs
new file mode 100644
index 00000000000..02f95fe5604
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-ice-101862.rs
@@ -0,0 +1,12 @@
+// issue: rust-lang/rust#101852
+// ICE opaque type with non-universal region substs
+
+pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
+//~^ WARN function cannot return without recursing
+    vec![].append(&mut ice(x.as_ref()));
+    //~^ ERROR expected generic type parameter, found `&str`
+
+    Vec::new()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.stderr
new file mode 100644
index 00000000000..f4148720c33
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-ice-101862.stderr
@@ -0,0 +1,24 @@
+warning: function cannot return without recursing
+  --> $DIR/recursive-ice-101862.rs:4:1
+   |
+LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |     vec![].append(&mut ice(x.as_ref()));
+   |                        --------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
+error[E0792]: expected generic type parameter, found `&str`
+  --> $DIR/recursive-ice-101862.rs:6:5
+   |
+LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
+   |               --------------- this generic parameter must be used with a generic type parameter
+LL |
+LL |     vec![].append(&mut ice(x.as_ref()));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/inference/str-as-char.stderr b/tests/ui/inference/str-as-char.stderr
index 216f4cda698..4ca71c5f067 100644
--- a/tests/ui/inference/str-as-char.stderr
+++ b/tests/ui/inference/str-as-char.stderr
@@ -4,7 +4,7 @@ error: character literal may only contain one codepoint
 LL |     let _: &str = '"""';
    |                   ^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _: &str = "\"\"\"";
    |                   ~~~~~~~~
@@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
 LL |     let _: &str = '\"\"\"';
    |                   ^^^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _: &str = "\"\"\"";
-   |                   ~~~~~~~~
+   |                   ~      ~
 
 error: character literal may only contain one codepoint
   --> $DIR/str-as-char.rs:10:19
@@ -26,7 +26,7 @@ error: character literal may only contain one codepoint
 LL |     let _: &str = '"\"\"\\"\\"';
    |                   ^^^^^^^^^^^^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _: &str = "\"\"\\"\\"\\\"";
    |                   ~~~~~~~~~~~~~~~~~~~~
@@ -39,10 +39,10 @@ LL |     let _: &str = 'a';
    |            |
    |            expected due to this
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _: &str = "a";
-   |                   ~~~
+   |                   ~ ~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/issues/issue-23589.stderr b/tests/ui/issues/issue-23589.stderr
index 1a91f5e04db..21d383b0e8c 100644
--- a/tests/ui/issues/issue-23589.stderr
+++ b/tests/ui/issues/issue-23589.stderr
@@ -15,10 +15,10 @@ error[E0308]: mismatched types
 LL |     let v: Vec(&str) = vec!['1', '2'];
    |                             ^^^ expected `&str`, found `char`
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let v: Vec(&str) = vec!["1", '2'];
-   |                             ~~~
+   |                             ~ ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lexer/lex-bad-char-literals-2.stderr b/tests/ui/lexer/lex-bad-char-literals-2.stderr
index 1518a37ab53..76cde00404a 100644
--- a/tests/ui/lexer/lex-bad-char-literals-2.stderr
+++ b/tests/ui/lexer/lex-bad-char-literals-2.stderr
@@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
 LL |     'nope'
    |     ^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     "nope"
-   |     ~~~~~~
+   |     ~    ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lexer/lex-bad-char-literals-3.stderr b/tests/ui/lexer/lex-bad-char-literals-3.stderr
index 62a5e424cb4..3f339b2ef7d 100644
--- a/tests/ui/lexer/lex-bad-char-literals-3.stderr
+++ b/tests/ui/lexer/lex-bad-char-literals-3.stderr
@@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
 LL | static c: char = '●●';
    |                  ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL | static c: char = "●●";
-   |                  ~~~~
+   |                  ~  ~
 
 error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-3.rs:5:20
@@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
 LL |     let ch: &str = '●●';
    |                    ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let ch: &str = "●●";
-   |                    ~~~~
+   |                    ~  ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lexer/lex-bad-char-literals-5.stderr b/tests/ui/lexer/lex-bad-char-literals-5.stderr
index 184817a6579..8004157e87f 100644
--- a/tests/ui/lexer/lex-bad-char-literals-5.stderr
+++ b/tests/ui/lexer/lex-bad-char-literals-5.stderr
@@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
 LL | static c: char = '\x10\x10';
    |                  ^^^^^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL | static c: char = "\x10\x10";
-   |                  ~~~~~~~~~~
+   |                  ~        ~
 
 error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-5.rs:5:20
@@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
 LL |     let ch: &str = '\x10\x10';
    |                    ^^^^^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let ch: &str = "\x10\x10";
-   |                    ~~~~~~~~~~
+   |                    ~        ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lexer/lex-bad-char-literals-6.stderr b/tests/ui/lexer/lex-bad-char-literals-6.stderr
index 2fe30304a50..96d409d59bb 100644
--- a/tests/ui/lexer/lex-bad-char-literals-6.stderr
+++ b/tests/ui/lexer/lex-bad-char-literals-6.stderr
@@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
 LL |     let x: &str = 'ab';
    |                   ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let x: &str = "ab";
-   |                   ~~~~
+   |                   ~  ~
 
 error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-6.rs:4:19
@@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
 LL |     let y: char = 'cd';
    |                   ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let y: char = "cd";
-   |                   ~~~~
+   |                   ~  ~
 
 error: character literal may only contain one codepoint
   --> $DIR/lex-bad-char-literals-6.rs:6:13
@@ -26,10 +26,10 @@ error: character literal may only contain one codepoint
 LL |     let z = 'ef';
    |             ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let z = "ef";
-   |             ~~~~
+   |             ~  ~
 
 error[E0308]: mismatched types
   --> $DIR/lex-bad-char-literals-6.rs:13:20
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed b/tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed
new file mode 100644
index 00000000000..b12139b0b40
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-1.fixed
@@ -0,0 +1,6 @@
+//@ run-rustfix
+fn main() {
+    println!("1 + 1");
+    //~^ ERROR unterminated character literal
+    //~| ERROR lifetimes cannot start with a number
+}
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-1.rs b/tests/ui/lexer/lex-bad-str-literal-as-char-1.rs
new file mode 100644
index 00000000000..6548792f33b
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-1.rs
@@ -0,0 +1,6 @@
+//@ run-rustfix
+fn main() {
+    println!('1 + 1');
+    //~^ ERROR unterminated character literal
+    //~| ERROR lifetimes cannot start with a number
+}
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr
new file mode 100644
index 00000000000..57c5f82704e
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-1.stderr
@@ -0,0 +1,20 @@
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-str-literal-as-char-1.rs:3:20
+   |
+LL |     println!('1 + 1');
+   |                    ^^^
+   |
+help: if you meant to write a string literal, use double quotes
+   |
+LL |     println!("1 + 1");
+   |              ~     ~
+
+error: lifetimes cannot start with a number
+  --> $DIR/lex-bad-str-literal-as-char-1.rs:3:14
+   |
+LL |     println!('1 + 1');
+   |              ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed b/tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed
new file mode 100644
index 00000000000..3ccec537c6c
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-2.fixed
@@ -0,0 +1,4 @@
+//@ run-rustfix
+fn main() {
+    println!(" 1 + 1"); //~ ERROR character literal may only contain one codepoint
+}
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-2.rs b/tests/ui/lexer/lex-bad-str-literal-as-char-2.rs
new file mode 100644
index 00000000000..8af72e47dbb
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-2.rs
@@ -0,0 +1,4 @@
+//@ run-rustfix
+fn main() {
+    println!(' 1 + 1'); //~ ERROR character literal may only contain one codepoint
+}
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr
new file mode 100644
index 00000000000..f64761af641
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-2.stderr
@@ -0,0 +1,13 @@
+error: character literal may only contain one codepoint
+  --> $DIR/lex-bad-str-literal-as-char-2.rs:3:14
+   |
+LL |     println!(' 1 + 1');
+   |              ^^^^^^^^
+   |
+help: if you meant to write a string literal, use double quotes
+   |
+LL |     println!(" 1 + 1");
+   |              ~      ~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-3.rs b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rs
new file mode 100644
index 00000000000..0ae227da5f1
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rs
@@ -0,0 +1,7 @@
+//@ revisions: rust2015 rust2018 rust2021
+//@[rust2018] edition:2018
+//@[rust2021] edition:2021
+fn main() {
+    println!('hello world');
+    //[rust2015,rust2018,rust2021]~^ ERROR unterminated character literal
+}
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr
new file mode 100644
index 00000000000..06f12742667
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2015.stderr
@@ -0,0 +1,14 @@
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
+   |
+LL |     println!('hello world');
+   |                          ^^^
+   |
+help: if you meant to write a string literal, use double quotes
+   |
+LL |     println!("hello world");
+   |              ~           ~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr
new file mode 100644
index 00000000000..06f12742667
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2018.stderr
@@ -0,0 +1,14 @@
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
+   |
+LL |     println!('hello world');
+   |                          ^^^
+   |
+help: if you meant to write a string literal, use double quotes
+   |
+LL |     println!("hello world");
+   |              ~           ~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr
new file mode 100644
index 00000000000..06f12742667
--- /dev/null
+++ b/tests/ui/lexer/lex-bad-str-literal-as-char-3.rust2021.stderr
@@ -0,0 +1,14 @@
+error[E0762]: unterminated character literal
+  --> $DIR/lex-bad-str-literal-as-char-3.rs:5:26
+   |
+LL |     println!('hello world');
+   |                          ^^^
+   |
+help: if you meant to write a string literal, use double quotes
+   |
+LL |     println!("hello world");
+   |              ~           ~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0762`.
diff --git a/tests/ui/nll/ice-106874.rs b/tests/ui/nll/ice-106874.rs
new file mode 100644
index 00000000000..9337eee961b
--- /dev/null
+++ b/tests/ui/nll/ice-106874.rs
@@ -0,0 +1,48 @@
+// issue: rust-lang/rust#106874
+// ICE BoundUniversalRegionError
+
+use std::marker::PhantomData;
+use std::rc::Rc;
+
+pub fn func<V, F: Fn(&mut V)>(f: F) -> A<impl X> {
+    A(B(C::new(D::new(move |st| f(st)))))
+    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR implementation of `Fn` is not general enough
+    //~| ERROR implementation of `FnOnce` is not general enough
+    //~| ERROR higher-ranked subtype error
+    //~| ERROR higher-ranked subtype error
+}
+
+trait X {}
+trait Y {
+    type V;
+}
+
+struct A<T>(T);
+
+struct B<T>(Rc<T>);
+impl<T> X for B<T> {}
+
+struct C<T: Y>(T::V);
+impl<T: Y> C<T> {
+    fn new(_: T) -> Rc<Self> {
+        todo!()
+    }
+}
+struct D<V, F>(F, PhantomData<fn(&mut V)>);
+
+impl<V, F> D<V, F> {
+    fn new(_: F) -> Self {
+        todo!()
+    }
+}
+impl<V, F: Fn(&mut V)> Y for D<V, F> {
+    type V = V;
+}
+
+pub fn main() {}
diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr
new file mode 100644
index 00000000000..ead4d490a62
--- /dev/null
+++ b/tests/ui/nll/ice-106874.stderr
@@ -0,0 +1,90 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:5
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`...
+   = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:5
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`...
+   = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: implementation of `Fn` is not general enough
+  --> $DIR/ice-106874.rs:8:7
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:7
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+
+error: implementation of `Fn` is not general enough
+  --> $DIR/ice-106874.rs:8:7
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:9
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |         ^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+
+error: implementation of `Fn` is not general enough
+  --> $DIR/ice-106874.rs:8:9
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:9
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+
+error: higher-ranked subtype error
+  --> $DIR/ice-106874.rs:8:41
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |                                         ^
+
+error: higher-ranked subtype error
+  --> $DIR/ice-106874.rs:8:41
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |                                         ^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/parser/issues/issue-64732.rs b/tests/ui/parser/issues/issue-64732.rs
index 2db51ea6042..ff0f97ea211 100644
--- a/tests/ui/parser/issues/issue-64732.rs
+++ b/tests/ui/parser/issues/issue-64732.rs
@@ -5,5 +5,5 @@ fn main() {
     //~| HELP if you meant to write a byte string literal, use double quotes
     let _bar = 'hello';
     //~^ ERROR character literal may only contain one codepoint
-    //~| HELP if you meant to write a `str` literal, use double quotes
+    //~| HELP if you meant to write a string literal, use double quotes
 }
diff --git a/tests/ui/parser/issues/issue-64732.stderr b/tests/ui/parser/issues/issue-64732.stderr
index 80462549377..7ec2df6d3bf 100644
--- a/tests/ui/parser/issues/issue-64732.stderr
+++ b/tests/ui/parser/issues/issue-64732.stderr
@@ -7,7 +7,7 @@ LL |     let _foo = b'hello\0';
 help: if you meant to write a byte string literal, use double quotes
    |
 LL |     let _foo = b"hello\0";
-   |                ~~~~~~~~~~
+   |                ~~       ~
 
 error: character literal may only contain one codepoint
   --> $DIR/issue-64732.rs:6:16
@@ -15,10 +15,10 @@ error: character literal may only contain one codepoint
 LL |     let _bar = 'hello';
    |                ^^^^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _bar = "hello";
-   |                ~~~~~~~
+   |                ~     ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/unicode-character-literal.fixed b/tests/ui/parser/unicode-character-literal.fixed
index 9e31890151c..e401ecaf5da 100644
--- a/tests/ui/parser/unicode-character-literal.fixed
+++ b/tests/ui/parser/unicode-character-literal.fixed
@@ -7,12 +7,12 @@ fn main() {
     let _spade = "♠️";
     //~^ ERROR: character literal may only contain one codepoint
     //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
-    //~| HELP: if you meant to write a `str` literal, use double quotes
+    //~| HELP: if you meant to write a string literal, use double quotes
 
     let _s = "ṩ̂̊";
     //~^ ERROR: character literal may only contain one codepoint
     //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
-    //~| HELP: if you meant to write a `str` literal, use double quotes
+    //~| HELP: if you meant to write a string literal, use double quotes
 
     let _a = 'Å';
     //~^ ERROR: character literal may only contain one codepoint
diff --git a/tests/ui/parser/unicode-character-literal.rs b/tests/ui/parser/unicode-character-literal.rs
index d886e5b26a5..428e4e1ac5a 100644
--- a/tests/ui/parser/unicode-character-literal.rs
+++ b/tests/ui/parser/unicode-character-literal.rs
@@ -7,12 +7,12 @@ fn main() {
     let _spade = '♠️';
     //~^ ERROR: character literal may only contain one codepoint
     //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
-    //~| HELP: if you meant to write a `str` literal, use double quotes
+    //~| HELP: if you meant to write a string literal, use double quotes
 
     let _s = 'ṩ̂̊';
     //~^ ERROR: character literal may only contain one codepoint
     //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
-    //~| HELP: if you meant to write a `str` literal, use double quotes
+    //~| HELP: if you meant to write a string literal, use double quotes
 
     let _a = 'Å';
     //~^ ERROR: character literal may only contain one codepoint
diff --git a/tests/ui/parser/unicode-character-literal.stderr b/tests/ui/parser/unicode-character-literal.stderr
index 5cd3bd0fe69..726cde2b413 100644
--- a/tests/ui/parser/unicode-character-literal.stderr
+++ b/tests/ui/parser/unicode-character-literal.stderr
@@ -9,10 +9,10 @@ note: this `♠` is followed by the combining mark `\u{fe0f}`
    |
 LL |     let _spade = '♠️';
    |                   ^
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _spade = "♠️";
-   |                  ~~~
+   |                  ~ ~
 
 error: character literal may only contain one codepoint
   --> $DIR/unicode-character-literal.rs:12:14
@@ -25,10 +25,10 @@ note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
    |
 LL |     let _s = 'ṩ̂̊';
    |               ^
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     let _s = "ṩ̂̊";
-   |              ~~~
+   |              ~ ~
 
 error: character literal may only contain one codepoint
   --> $DIR/unicode-character-literal.rs:17:14
diff --git a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs
new file mode 100644
index 00000000000..87ce4f1e14d
--- /dev/null
+++ b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.rs
@@ -0,0 +1,15 @@
+// issue: rust-lang/rust#105047
+// ICE raw ptr comparison should already be caught in the trait systems
+
+#![feature(raw_ref_op)]
+
+const RCZ: *const i32 = &raw const *&0;
+
+const fn f() {
+    if let RCZ = &raw const *&0 { }
+    //~^ WARN function pointers and raw pointers not derived from integers in patterns
+    //~| ERROR pointers cannot be reliably compared during const eval
+    //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+fn main() {}
diff --git a/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr
new file mode 100644
index 00000000000..9c472cda244
--- /dev/null
+++ b/tests/ui/raw-ref-op/const-eval-compare-ice-105047.stderr
@@ -0,0 +1,31 @@
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/const-eval-compare-ice-105047.rs:9:12
+   |
+LL |     if let RCZ = &raw const *&0 { }
+   |            ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+error: pointers cannot be reliably compared during const eval
+  --> $DIR/const-eval-compare-ice-105047.rs:9:12
+   |
+LL |     if let RCZ = &raw const *&0 { }
+   |            ^^^
+   |
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/const-eval-compare-ice-105047.rs:9:12
+   |
+LL |     if let RCZ = &raw const *&0 { }
+   |            ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
diff --git a/tests/ui/specialization/broken-mir-drop-glue-107228.rs b/tests/ui/specialization/broken-mir-drop-glue-107228.rs
new file mode 100644
index 00000000000..5a6dbf9ffc7
--- /dev/null
+++ b/tests/ui/specialization/broken-mir-drop-glue-107228.rs
@@ -0,0 +1,28 @@
+// issue: rust-lang/rust#107228
+// ICE broken MIR in DropGlue
+//@ compile-flags: -Zvalidate-mir
+//@ check-pass
+
+#![feature(specialization)]
+#![crate_type="lib"]
+#![allow(incomplete_features)]
+
+pub(crate) trait SpecTrait {
+    type Assoc;
+}
+
+impl<C> SpecTrait for C {
+    default type Assoc = Vec<Self>;
+}
+
+pub(crate) struct AssocWrap<C: SpecTrait> {
+    _assoc: C::Assoc,
+}
+
+fn instantiate<C: SpecTrait>() -> AssocWrap<C> {
+    loop {}
+}
+
+pub fn main() {
+    instantiate::<()>();
+}
diff --git a/tests/ui/str/str-as-char.stderr b/tests/ui/str/str-as-char.stderr
index 44ec079e929..0638d371c17 100644
--- a/tests/ui/str/str-as-char.stderr
+++ b/tests/ui/str/str-as-char.stderr
@@ -4,10 +4,10 @@ error: character literal may only contain one codepoint
 LL |     println!('●●');
    |              ^^^^
    |
-help: if you meant to write a `str` literal, use double quotes
+help: if you meant to write a string literal, use double quotes
    |
 LL |     println!("●●");
-   |              ~~~~
+   |              ~  ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs b/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs
new file mode 100644
index 00000000000..57f814bc81e
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-canonicalize-re-error.rs
@@ -0,0 +1,28 @@
+//@ compile-flags: -Znext-solver
+
+trait Tr<'a> {}
+
+// Fulfillment in the new solver relies on an invariant to hold: Either
+// `has_changed` is true, or computing a goal's certainty is idempotent.
+// This isn't true for `ReError`, which we used to pass through in the
+// canonicalizer even on input mode, which can cause a goal to go from
+// ambig => pass, but we don't consider `has_changed` when the response
+// only contains region constraints (since we usually uniquify regions).
+//
+//   In this test:
+// Implicit negative coherence tries to prove `W<?0>: Constrain<'?1>`,
+// which will then match with the impl below. This constrains `'?1` to
+// `ReError`, but still bails w/ ambiguity bc we can't prove `?0: Sized`.
+// Then, when we recompute the goal `W<?0>: Constrain<'error>`, when
+// collecting ambiguities and overflows, we end up assembling a default
+// error candidate w/o ambiguity, which causes the goal to pass, and ICE.
+impl<'a, A: ?Sized> Tr<'a> for W<A> {}
+struct W<A: ?Sized>(A);
+impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
+//~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>`
+
+trait Constrain<'a> {}
+impl<A: Sized> Constrain<'missing> for W<A> {}
+//~^ ERROR use of undeclared lifetime name `'missing`
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr b/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr
new file mode 100644
index 00000000000..cf85c52fb42
--- /dev/null
+++ b/tests/ui/traits/next-solver/dont-canonicalize-re-error.stderr
@@ -0,0 +1,21 @@
+error[E0261]: use of undeclared lifetime name `'missing`
+  --> $DIR/dont-canonicalize-re-error.rs:25:26
+   |
+LL | impl<A: Sized> Constrain<'missing> for W<A> {}
+   |      -                   ^^^^^^^^ undeclared lifetime
+   |      |
+   |      help: consider introducing lifetime `'missing` here: `'missing,`
+
+error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>`
+  --> $DIR/dont-canonicalize-re-error.rs:21:1
+   |
+LL | impl<'a, A: ?Sized> Tr<'a> for W<A> {}
+   | ----------------------------------- first implementation here
+LL | struct W<A: ?Sized>(A);
+LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0261.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs
new file mode 100644
index 00000000000..3af299e5b11
--- /dev/null
+++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs
@@ -0,0 +1,15 @@
+trait FromResidual<R = <Self as Try>::Residual> {
+    fn from_residual(residual: R) -> Self;
+}
+
+trait Try {
+    type Residual;
+}
+
+fn w<'a, T: 'a, F: Fn(&'a T)>() {
+    let b: &dyn FromResidual = &();
+    //~^ ERROR: the trait `FromResidual` cannot be made into an object
+    //~| ERROR: the trait `FromResidual` cannot be made into an object
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
new file mode 100644
index 00000000000..d5e9b1be63b
--- /dev/null
+++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr
@@ -0,0 +1,33 @@
+error[E0038]: the trait `FromResidual` cannot be made into an object
+  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17
+   |
+LL |     let b: &dyn FromResidual = &();
+   |                 ^^^^^^^^^^^^
+   |
+   = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
+
+error[E0038]: the trait `FromResidual` cannot be made into an object
+  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12
+   |
+LL |     let b: &dyn FromResidual = &();
+   |            ^^^^^^^^^^^^^^^^^ `FromResidual` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8
+   |
+LL | trait FromResidual<R = <Self as Try>::Residual> {
+   |       ------------ this trait cannot be made into an object...
+LL |     fn from_residual(residual: R) -> Self;
+   |        ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter
+help: consider turning `from_residual` into a method by giving it a `&self` argument
+   |
+LL |     fn from_residual(&self, residual: R) -> Self;
+   |                      ++++++
+help: alternatively, consider constraining `from_residual` so it does not apply to trait objects
+   |
+LL |     fn from_residual(residual: R) -> Self where Self: Sized;
+   |                                           +++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
new file mode 100644
index 00000000000..023991c29d0
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
@@ -0,0 +1,36 @@
+// issue: rust-lang/rust#99945
+// ICE Failed to normalize
+
+#![feature(type_alias_impl_trait)]
+
+trait Widget<E> {
+    type State;
+
+    fn make_state(&self) -> Self::State;
+}
+
+impl<E> Widget<E> for () {
+    type State = ();
+
+    fn make_state(&self) -> Self::State {}
+}
+
+struct StatefulWidget<F>(F);
+
+type StateWidget<'a> = impl Widget<&'a ()>;
+
+impl<F: for<'a> Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget<F> {
+    type State = ();
+
+    fn make_state(&self) -> Self::State {}
+}
+
+fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
+    StatefulWidget(build)
+    //~^ ERROR expected generic lifetime parameter, found `'a`
+}
+
+fn main() {
+    new_stateful_widget(|_| ()).make_state();
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
new file mode 100644
index 00000000000..0c76feae198
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/failed-to-normalize-ice-99945.rs:34:29
+   |
+LL | type StateWidget<'a> = impl Widget<&'a ()>;
+   |                        ------------------- the expected opaque type
+...
+LL |     new_stateful_widget(|_| ()).make_state();
+   |                             ^^ expected opaque type, found `()`
+   |
+   = note: expected opaque type `StateWidget<'_>`
+                found unit type `()`
+
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/failed-to-normalize-ice-99945.rs:29:5
+   |
+LL | type StateWidget<'a> = impl Widget<&'a ()>;
+   |                  -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     StatefulWidget(build)
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0792.
+For more information about an error, try `rustc --explain E0308`.