about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-10-01 14:36:51 +0000
committerbors <bors@rust-lang.org>2025-10-01 14:36:51 +0000
commitd4ae855111df8c7ee255bea4c112e74b7d72cf45 (patch)
tree1061cf71bca8dcba2ac269aaa753d99f1fb12daa
parent1e1a39441bd11aba541a48ba714d939490fc7b85 (diff)
parentde20efd01e560f74649b95c1e48c8e5e21c82269 (diff)
downloadrust-d4ae855111df8c7ee255bea4c112e74b7d72cf45.tar.gz
rust-d4ae855111df8c7ee255bea4c112e74b7d72cf45.zip
Auto merge of #147220 - Zalathar:rollup-fubv0wy, r=Zalathar
Rollup of 11 pull requests

Successful merges:

 - rust-lang/rust#146918 (add regression test)
 - rust-lang/rust#146980 (simplify setup_constraining_predicates, and note it is potentially cubic)
 - rust-lang/rust#147170 (compiletest: Pass around `DirectiveLine` instead of bare strings)
 - rust-lang/rust#147180 (add tests)
 - rust-lang/rust#147188 (Remove usage of `compiletest-use-stage0-libtest` from CI)
 - rust-lang/rust#147189 (Replace `rustc_span::Span` with a stripped down version for librustdoc's highlighter)
 - rust-lang/rust#147199 (remove outdated comment in (inner) `InferCtxt`)
 - rust-lang/rust#147200 (Fix autodiff empty ret regression)
 - rust-lang/rust#147209 (Remove `no-remap-src-base` from tests)
 - rust-lang/rust#147213 (Fix broken STD build for ESP-IDF)
 - rust-lang/rust#147217 (Don't create a top-level `true` directory when running UI tests)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--bootstrap.example.toml3
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs53
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs17
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/regions.rs2
-rw-r--r--library/std/src/sys/net/hostname/mod.rs2
-rw-r--r--src/bootstrap/defaults/bootstrap.dist.toml2
-rw-r--r--src/bootstrap/src/core/builder/mod.rs2
-rw-r--r--src/ci/citool/tests/test-jobs.yml2
-rw-r--r--src/ci/docker/host-x86_64/pr-check-1/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile1
-rw-r--r--src/librustdoc/html/highlight.rs3
-rw-r--r--src/librustdoc/html/highlight/tests.rs14
-rw-r--r--src/librustdoc/html/render/context.rs3
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/render/span_map.rs68
-rw-r--r--src/librustdoc/html/sources.rs7
-rw-r--r--src/tools/compiletest/src/directives.rs217
-rw-r--r--src/tools/compiletest/src/directives/auxiliary.rs35
-rw-r--r--src/tools/compiletest/src/directives/cfg.rs14
-rw-r--r--src/tools/compiletest/src/directives/needs.rs6
-rw-r--r--src/tools/compiletest/src/runtest/debugger.rs27
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs6
-rw-r--r--tests/codegen-llvm/autodiff/abi_handling.rs4
-rw-r--r--tests/codegen-llvm/autodiff/batched.rs2
-rw-r--r--tests/codegen-llvm/autodiff/scalar.rs2
-rw-r--r--tests/codegen-llvm/autodiff/sret.rs2
-rw-r--r--tests/codegen-llvm/autodiff/void_ret.rs41
-rw-r--r--tests/ui-fulldeps/mod_dir_path_canonicalized.rs1
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.rs5
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.stderr2
-rw-r--r--tests/ui/errors/auxiliary/remapped_dep.rs2
-rw-r--r--tests/ui/errors/remap-path-prefix-reverse.local-self.stderr2
-rw-r--r--tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr2
-rw-r--r--tests/ui/errors/remap-path-prefix-reverse.rs1
-rw-r--r--tests/ui/errors/remap-path-prefix.rs2
-rw-r--r--tests/ui/indexing/ambiguity-after-deref-step.rs9
-rw-r--r--tests/ui/indexing/ambiguity-after-deref-step.stderr17
-rw-r--r--tests/ui/methods/overflow-if-subtyping.rs30
-rw-r--r--tests/ui/proc-macro/expand-expr.rs2
-rw-r--r--tests/ui/proc-macro/pretty-print-hack-show.rs1
-rw-r--r--tests/ui/traits/next-solver/forced-ambiguity-typenum-ice.rs60
43 files changed, 420 insertions, 268 deletions
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 0a39c6d8f24..f623a3db002 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -476,9 +476,6 @@
 # when the stage 0 compiler is actually built from in-tree sources.
 #build.compiletest-allow-stage0 = false
 
-# Whether to use the precompiled stage0 libtest with compiletest.
-#build.compiletest-use-stage0-libtest = true
-
 # Default value for the `--extra-checks` flag of tidy.
 #
 # See `./x test tidy --help` for details.
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index c3485f56391..4a749642265 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -378,5 +378,12 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
 
     let call = builder.call(enzyme_ty, None, None, ad_fn, &args, None, None);
 
-    builder.store_to_place(call, dest.val);
+    let fn_ret_ty = builder.cx.val_ty(call);
+    if fn_ret_ty != builder.cx.type_void() && fn_ret_ty != builder.cx.type_struct(&[], false) {
+        // If we return void or an empty struct, then our caller (due to how we generated it)
+        // does not expect a return value. As such, we have no pointer (or place) into which
+        // we could store our value, and would store into an undef, which would cause UB.
+        // As such, we just ignore the return value in those cases.
+        builder.store_to_place(call, dest.val);
+    }
 }
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 2a633810cd7..f8d0ea3e7bf 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -167,15 +167,20 @@ pub(crate) fn setup_constraining_predicates<'tcx>(
     // which is `O(nt)` where `t` is the depth of type-parameter constraints,
     // remembering that `t` should be less than 7 in practice.
     //
+    // FIXME(hkBst): the big-O bound above would be accurate for the number
+    // of calls to `parameters_for`, which itself is some O(complexity of type).
+    // That would make this potentially cubic instead of merely quadratic...
+    // ...unless we cache those `parameters_for` calls.
+    //
     // Basically, I iterate over all projections and swap every
     // "ready" projection to the start of the list, such that
     // all of the projections before `i` are topologically sorted
     // and constrain all the parameters in `input_parameters`.
     //
-    // In the example, `input_parameters` starts by containing `U` - which
-    // is constrained by the trait-ref - and so on the first pass we
+    // In the first example, `input_parameters` starts by containing `U`,
+    // which is constrained by the self type `U`. Then, on the first pass we
     // observe that `<U as Iterator>::Item = T` is a "ready" projection that
-    // constrains `T` and swap it to front. As it is the sole projection,
+    // constrains `T` and swap it to the front. As it is the sole projection,
     // no more swaps can take place afterwards, with the result being
     //   * <U as Iterator>::Item = T
     //   * T: Debug
@@ -193,33 +198,25 @@ pub(crate) fn setup_constraining_predicates<'tcx>(
         for j in i..predicates.len() {
             // Note that we don't have to care about binders here,
             // as the impl trait ref never contains any late-bound regions.
-            if let ty::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() {
-                // Special case: watch out for some kind of sneaky attempt
-                // to project out an associated type defined by this very
-                // trait.
-                let unbound_trait_ref = projection.projection_term.trait_ref(tcx);
-                if Some(unbound_trait_ref) == impl_trait_ref {
-                    continue;
-                }
-
-                // A projection depends on its input types and determines its output
-                // type. For example, if we have
-                //     `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
-                // Then the projection only applies if `T` is known, but it still
-                // does not determine `U`.
-                let inputs = parameters_for(tcx, projection.projection_term, true);
-                let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
-                if !relies_only_on_inputs {
-                    continue;
-                }
+            if let ty::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() &&
+
+            // Special case: watch out for some kind of sneaky attempt to
+            // project out an associated type defined by this very trait.
+            !impl_trait_ref.is_some_and(|t| t == projection.projection_term.trait_ref(tcx)) &&
+
+            // A projection depends on its input types and determines its output
+            // type. For example, if we have
+            //     `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
+            // then the projection only applies if `T` is known, but it still
+            // does not determine `U`.
+                parameters_for(tcx, projection.projection_term, true).iter().all(|p| input_parameters.contains(p))
+            {
                 input_parameters.extend(parameters_for(tcx, projection.term, false));
-            } else {
-                continue;
+
+                predicates.swap(i, j);
+                i += 1;
+                changed = true;
             }
-            // fancy control flow to bypass borrow checker
-            predicates.swap(i, j);
-            i += 1;
-            changed = true;
         }
         debug!(
             "setup_constraining_predicates: predicates={:?} \
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c9fc124d3bf..f3ebfde06ab 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -131,23 +131,6 @@ pub struct InferCtxtInner<'tcx> {
     /// `$0: 'static`. This will get checked later by regionck. (We
     /// can't generally check these things right away because we have
     /// to wait until types are resolved.)
-    ///
-    /// These are stored in a map keyed to the id of the innermost
-    /// enclosing fn body / static initializer expression. This is
-    /// because the location where the obligation was incurred can be
-    /// relevant with respect to which sublifetime assumptions are in
-    /// place. The reason that we store under the fn-id, and not
-    /// something more fine-grained, is so that it is easier for
-    /// regionck to be sure that it has found *all* the region
-    /// obligations (otherwise, it's easy to fail to walk to a
-    /// particular node-id).
-    ///
-    /// Before running `resolve_regions_and_report_errors`, the creator
-    /// of the inference context is expected to invoke
-    /// [`InferCtxt::process_registered_region_obligations`]
-    /// for each body-id in this map, which will process the
-    /// obligations within. This is expected to be done 'late enough'
-    /// that all type inference variables have been bound and so forth.
     region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
 
     /// The outlives bounds that we assume must hold about placeholders that
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index a2e6ef6f0fe..d58c264841c 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -473,7 +473,10 @@ where
         // fails to reach a fixpoint but ends up getting an error after
         // running for some additional step.
         //
-        // cc trait-system-refactor-initiative#105
+        // FIXME(@lcnr): While I believe an error here to be possible, we
+        // currently don't have any test which actually triggers it. @lqd
+        // created a minimization for an ICE in typenum, but that one no
+        // longer fails here. cc trait-system-refactor-initiative#105.
         let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
         let certainty = Certainty::Maybe { cause, opaque_types_jank: OpaqueTypesJank::AllGood };
         self.probe_trait_candidate(source)
diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs
index 2b33b8ac9f8..debc4fda15a 100644
--- a/compiler/rustc_trait_selection/src/regions.rs
+++ b/compiler/rustc_trait_selection/src/regions.rs
@@ -77,6 +77,8 @@ impl<'tcx> InferCtxt<'tcx> {
     ///
     /// Prefer this method over `resolve_regions_with_normalize`, unless you are
     /// doing something specific for normalization.
+    ///
+    /// This function assumes that all infer variables are already constrained.
     fn resolve_regions(
         &self,
         body_id: LocalDefId,
diff --git a/library/std/src/sys/net/hostname/mod.rs b/library/std/src/sys/net/hostname/mod.rs
index a4b5b76059d..8ffe4894d71 100644
--- a/library/std/src/sys/net/hostname/mod.rs
+++ b/library/std/src/sys/net/hostname/mod.rs
@@ -1,5 +1,5 @@
 cfg_select! {
-    target_family = "unix" => {
+    all(target_family = "unix", not(target_os = "espidf")) => {
         mod unix;
         pub use unix::hostname;
     }
diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml
index b111a20f8d8..bb0592ce947 100644
--- a/src/bootstrap/defaults/bootstrap.dist.toml
+++ b/src/bootstrap/defaults/bootstrap.dist.toml
@@ -7,8 +7,6 @@ test-stage = 2
 doc-stage = 2
 # When compiling from source, you usually want all tools.
 extended = true
-# Use libtest built from the source tree instead of the precompiled one from stage 0.
-compiletest-use-stage0-libtest = false
 
 # Most users installing from source want to build all parts of the project from source.
 [llvm]
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 006dea4b98d..fc06db8f80b 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1145,7 +1145,7 @@ impl<'a> Builder<'a> {
                 test::RunMakeCargo,
             ),
             Kind::Miri => describe!(test::Crate),
-            Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
+            Kind::Bench => describe!(test::Crate, test::CrateLibrustc, test::CrateRustdoc),
             Kind::Doc => describe!(
                 doc::UnstableBook,
                 doc::UnstableBookGen,
diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml
index d82b3e7648e..512c8062857 100644
--- a/src/ci/citool/tests/test-jobs.yml
+++ b/src/ci/citool/tests/test-jobs.yml
@@ -27,7 +27,7 @@ runners:
     <<: *base-job
 envs:
   env-x86_64-apple-tests: &env-x86_64-apple-tests
-    SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
+    SCRIPT: ./x.py check compiletest && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
     RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
     RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
     # Ensure that host tooling is tested on our minimum supported macOS version.
diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
index 04ac0f33daf..776bbb12e44 100644
--- a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
+++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
@@ -43,7 +43,6 @@ ENV SCRIPT \
   python3 ../x.py check bootstrap && \
   /scripts/check-default-config-profiles.sh && \
   python3 ../x.py build src/tools/build-manifest && \
-  python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \
   python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
   python3 ../x.py check --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
   /scripts/validate-toolstate.sh && \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 95357d22937..278e40eb71f 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -90,5 +90,4 @@ ENV HOST_TARGET x86_64-unknown-linux-gnu
 COPY scripts/shared.sh /scripts/
 
 ENV SCRIPT /tmp/checktools.sh ../x.py && \
-  python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \
   python3 ../x.py test tests/rustdoc-gui --stage 2 --test-args "'--jobs 1'"
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index fad15573cde..1dcb4dcc3ff 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -12,15 +12,16 @@ use std::iter;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
+use rustc_span::BytePos;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, DUMMY_SP, Span};
 
 use super::format;
 use crate::clean::PrimitiveType;
 use crate::display::Joined as _;
 use crate::html::escape::EscapeBodyText;
 use crate::html::macro_expansion::ExpandedCode;
+use crate::html::render::span_map::{DUMMY_SP, Span};
 use crate::html::render::{Context, LinkFromSrc};
 
 /// This type is needed in case we want to render links on items to allow to go to their definition.
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 2603e887bea..4d1bee9b3a1 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -1,6 +1,7 @@
 use expect_test::expect_file;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_span::create_default_session_globals_then;
+use test::Bencher;
 
 use super::{DecorationInfo, write_code};
 
@@ -81,3 +82,16 @@ let a = 4;";
         expect_file!["fixtures/decorations.html"].assert_eq(&html);
     });
 }
+
+#[bench]
+fn bench_html_highlighting(b: &mut Bencher) {
+    let src = include_str!("../../../../compiler/rustc_ast/src/visit.rs");
+
+    create_default_session_globals_then(|| {
+        b.iter(|| {
+            let mut out = String::new();
+            write_code(&mut out, src, None, None, None);
+            out
+        });
+    });
+}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 5f92ab2fada..4c06d0da470 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -30,6 +30,7 @@ use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
 use crate::html::macro_expansion::ExpandedCode;
 use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
+use crate::html::render::span_map::Span;
 use crate::html::render::write_shared::write_shared;
 use crate::html::url_parts_builder::UrlPartsBuilder;
 use crate::html::{layout, sources, static_files};
@@ -139,7 +140,7 @@ pub(crate) struct SharedContext<'tcx> {
 
     /// Correspondence map used to link types used in the source code pages to allow to click on
     /// links to jump to the type's definition.
-    pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
+    pub(crate) span_correspondence_map: FxHashMap<Span, LinkFromSrc>,
     pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
     /// The [`Cache`] used during rendering.
     pub(crate) cache: Cache,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 97dcaf57cdf..d6371e4dbab 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -36,7 +36,7 @@ mod ordered_json;
 mod print_item;
 pub(crate) mod sidebar;
 mod sorted_template;
-mod span_map;
+pub(crate) mod span_map;
 mod type_layout;
 mod write_shared;
 
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index ef7ce33298d..bc9417b1bb1 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -8,11 +8,48 @@ use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::{BytePos, ExpnKind, Span};
+use rustc_span::{BytePos, ExpnKind};
 
 use crate::clean::{self, PrimitiveType, rustc_span};
 use crate::html::sources;
 
+/// This is a stripped down version of [`rustc_span::Span`] that only contains the start and end byte positions of the span.
+///
+/// Profiling showed that the `Span` interner was taking up a lot of the run-time when highlighting, and since we
+/// never actually use the context and parent that are stored in a normal `Span`, we can replace its usages with this
+/// one, which is much cheaper to construct.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub(crate) struct Span {
+    lo: BytePos,
+    hi: BytePos,
+}
+
+impl From<rustc_span::Span> for Span {
+    fn from(value: rustc_span::Span) -> Self {
+        Self { lo: value.lo(), hi: value.hi() }
+    }
+}
+
+impl Span {
+    pub(crate) fn lo(self) -> BytePos {
+        self.lo
+    }
+
+    pub(crate) fn hi(self) -> BytePos {
+        self.hi
+    }
+
+    pub(crate) fn with_lo(self, lo: BytePos) -> Self {
+        Self { lo, hi: self.hi() }
+    }
+
+    pub(crate) fn with_hi(self, hi: BytePos) -> Self {
+        Self { lo: self.lo(), hi }
+    }
+}
+
+pub(crate) const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0) };
+
 /// This enum allows us to store two different kinds of information:
 ///
 /// In case the `span` definition comes from the same crate, we can simply get the `span` and use
@@ -96,7 +133,7 @@ impl SpanMapVisitor<'_> {
                         })
                         .unwrap_or(path.span)
                 };
-                self.matches.insert(span, link);
+                self.matches.insert(span.into(), link);
             }
             Res::Local(_) if let Some(span) = self.tcx.hir_res_span(path.res) => {
                 let path_span = if only_use_last_segment
@@ -106,11 +143,12 @@ impl SpanMapVisitor<'_> {
                 } else {
                     path.span
                 };
-                self.matches.insert(path_span, LinkFromSrc::Local(clean::Span::new(span)));
+                self.matches.insert(path_span.into(), LinkFromSrc::Local(clean::Span::new(span)));
             }
             Res::PrimTy(p) => {
                 // FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
-                self.matches.insert(path.span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
+                self.matches
+                    .insert(path.span.into(), LinkFromSrc::Primitive(PrimitiveType::from(p)));
             }
             Res::Err => {}
             _ => {}
@@ -127,7 +165,7 @@ impl SpanMapVisitor<'_> {
             if cspan.inner().is_dummy() || cspan.cnum(self.tcx.sess) != LOCAL_CRATE {
                 return;
             }
-            self.matches.insert(span, LinkFromSrc::Doc(item.owner_id.to_def_id()));
+            self.matches.insert(span.into(), LinkFromSrc::Doc(item.owner_id.to_def_id()));
         }
     }
 
@@ -138,7 +176,7 @@ impl SpanMapVisitor<'_> {
     /// so, we loop until we find the macro definition by using `outer_expn_data` in a loop.
     /// Finally, we get the information about the macro itself (`span` if "local", `DefId`
     /// otherwise) and store it inside the span map.
-    fn handle_macro(&mut self, span: Span) -> bool {
+    fn handle_macro(&mut self, span: rustc_span::Span) -> bool {
         if !span.from_expansion() {
             return false;
         }
@@ -176,7 +214,7 @@ impl SpanMapVisitor<'_> {
         // The "call_site" includes the whole macro with its "arguments". We only want
         // the macro name.
         let new_span = new_span.with_hi(new_span.lo() + BytePos(macro_name.len() as u32));
-        self.matches.insert(new_span, link_from_src);
+        self.matches.insert(new_span.into(), link_from_src);
         true
     }
 
@@ -233,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
         intravisit::walk_path(self, path);
     }
 
-    fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: Span) {
+    fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: rustc_span::Span) {
         match *qpath {
             QPath::TypeRelative(qself, path) => {
                 if matches!(path.res, Res::Err) {
@@ -249,7 +287,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
                         self.handle_path(&path, false);
                     }
                 } else {
-                    self.infer_id(path.hir_id, Some(id), path.ident.span);
+                    self.infer_id(path.hir_id, Some(id), path.ident.span.into());
                 }
 
                 rustc_ast::visit::try_visit!(self.visit_ty_unambig(qself));
@@ -267,7 +305,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
         }
     }
 
-    fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
+    fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: rustc_span::Span, id: HirId) {
         // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another
         // file, we want to link to it. Otherwise no need to create a link.
         if !span.overlaps(m.spans.inner_span) {
@@ -275,8 +313,10 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
             // name only and not all the "mod foo;".
             if let Node::Item(item) = self.tcx.hir_node(id) {
                 let (ident, _) = item.expect_mod();
-                self.matches
-                    .insert(ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)));
+                self.matches.insert(
+                    ident.span.into(),
+                    LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)),
+                );
             }
         } else {
             // If it's a "mod foo {}", we want to look to its documentation page.
@@ -288,9 +328,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
     fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
         match expr.kind {
             ExprKind::MethodCall(segment, ..) => {
-                self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span)
+                self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span.into())
             }
-            ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span),
+            ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span.into()),
             _ => {
                 if self.handle_macro(expr.span) {
                     // We don't want to go deeper into the macro.
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 9c5518a780e..c79f63fbc20 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -348,7 +348,12 @@ pub(crate) fn print_src(
         highlight::write_code(
             fmt,
             s,
-            Some(highlight::HrefContext { context, file_span, root_path, current_href }),
+            Some(highlight::HrefContext {
+                context,
+                file_span: file_span.into(),
+                root_path,
+                current_href,
+            }),
             Some(decoration_info),
             Some(line_info),
         );
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index e84a2278766..e6916610190 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -63,9 +63,10 @@ impl EarlyProps {
             &mut poisoned,
             testfile,
             rdr,
-            &mut |DirectiveLine { line_number, raw_directive: ln, .. }| {
-                parse_and_update_aux(config, ln, testfile, line_number, &mut props.aux);
-                config.parse_and_update_revisions(testfile, line_number, ln, &mut props.revisions);
+            // (dummy comment to force args into vertical layout)
+            &mut |ref ln: DirectiveLine<'_>| {
+                parse_and_update_aux(config, ln, testfile, &mut props.aux);
+                config.parse_and_update_revisions(testfile, ln, &mut props.revisions);
             },
         );
 
@@ -367,8 +368,8 @@ impl TestProps {
                 &mut poisoned,
                 testfile,
                 file,
-                &mut |directive @ DirectiveLine { line_number, raw_directive: ln, .. }| {
-                    if !directive.applies_to_test_revision(test_revision) {
+                &mut |ref ln: DirectiveLine<'_>| {
+                    if !ln.applies_to_test_revision(test_revision) {
                         return;
                     }
 
@@ -378,7 +379,6 @@ impl TestProps {
                         ln,
                         ERROR_PATTERN,
                         testfile,
-                        line_number,
                         &mut self.error_patterns,
                         |r| r,
                     );
@@ -386,7 +386,6 @@ impl TestProps {
                         ln,
                         REGEX_ERROR_PATTERN,
                         testfile,
-                        line_number,
                         &mut self.regex_error_patterns,
                         |r| r,
                     );
@@ -395,7 +394,6 @@ impl TestProps {
                         ln,
                         DOC_FLAGS,
                         testfile,
-                        line_number,
                         &mut self.doc_flags,
                         |r| r,
                     );
@@ -414,7 +412,7 @@ impl TestProps {
                     }
 
                     if let Some(flags) =
-                        config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile, line_number)
+                        config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile)
                     {
                         let flags = split_flags(&flags);
                         for flag in &flags {
@@ -425,39 +423,28 @@ impl TestProps {
                         self.compile_flags.extend(flags);
                     }
                     if config
-                        .parse_name_value_directive(
-                            ln,
-                            INCORRECT_COMPILER_FLAGS,
-                            testfile,
-                            line_number,
-                        )
+                        .parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS, testfile)
                         .is_some()
                     {
                         panic!("`compiler-flags` directive should be spelled `compile-flags`");
                     }
 
-                    if let Some(edition) = config.parse_edition(ln, testfile, line_number) {
+                    if let Some(edition) = config.parse_edition(ln, testfile) {
                         // The edition is added at the start, since flags from //@compile-flags must
                         // be passed to rustc last.
                         self.compile_flags.insert(0, format!("--edition={}", edition.trim()));
                         has_edition = true;
                     }
 
-                    config.parse_and_update_revisions(
-                        testfile,
-                        line_number,
-                        ln,
-                        &mut self.revisions,
-                    );
+                    config.parse_and_update_revisions(testfile, ln, &mut self.revisions);
 
-                    if let Some(flags) =
-                        config.parse_name_value_directive(ln, RUN_FLAGS, testfile, line_number)
+                    if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS, testfile)
                     {
                         self.run_flags.extend(split_flags(&flags));
                     }
 
                     if self.pp_exact.is_none() {
-                        self.pp_exact = config.parse_pp_exact(ln, testfile, line_number);
+                        self.pp_exact = config.parse_pp_exact(ln, testfile);
                     }
 
                     config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
@@ -479,9 +466,7 @@ impl TestProps {
                     );
                     config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic);
 
-                    if let Some(m) =
-                        config.parse_name_value_directive(ln, PRETTY_MODE, testfile, line_number)
-                    {
+                    if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE, testfile) {
                         self.pretty_mode = m;
                     }
 
@@ -492,13 +477,12 @@ impl TestProps {
                     );
 
                     // Call a helper method to deal with aux-related directives.
-                    parse_and_update_aux(config, ln, testfile, line_number, &mut self.aux);
+                    parse_and_update_aux(config, ln, testfile, &mut self.aux);
 
                     config.push_name_value_directive(
                         ln,
                         EXEC_ENV,
                         testfile,
-                        line_number,
                         &mut self.exec_env,
                         Config::parse_env,
                     );
@@ -506,7 +490,6 @@ impl TestProps {
                         ln,
                         UNSET_EXEC_ENV,
                         testfile,
-                        line_number,
                         &mut self.unset_exec_env,
                         |r| r.trim().to_owned(),
                     );
@@ -514,7 +497,6 @@ impl TestProps {
                         ln,
                         RUSTC_ENV,
                         testfile,
-                        line_number,
                         &mut self.rustc_env,
                         Config::parse_env,
                     );
@@ -522,7 +504,6 @@ impl TestProps {
                         ln,
                         UNSET_RUSTC_ENV,
                         testfile,
-                        line_number,
                         &mut self.unset_rustc_env,
                         |r| r.trim().to_owned(),
                     );
@@ -530,7 +511,6 @@ impl TestProps {
                         ln,
                         FORBID_OUTPUT,
                         testfile,
-                        line_number,
                         &mut self.forbid_output,
                         |r| r,
                     );
@@ -566,7 +546,7 @@ impl TestProps {
                     }
 
                     if let Some(code) = config
-                        .parse_name_value_directive(ln, FAILURE_STATUS, testfile, line_number)
+                        .parse_name_value_directive(ln, FAILURE_STATUS, testfile)
                         .and_then(|code| code.trim().parse::<i32>().ok())
                     {
                         self.failure_status = Some(code);
@@ -588,7 +568,6 @@ impl TestProps {
                         ln,
                         ASSEMBLY_OUTPUT,
                         testfile,
-                        line_number,
                         &mut self.assembly_output,
                         |r| r.trim().to_string(),
                     );
@@ -602,7 +581,7 @@ impl TestProps {
                     // Unlike the other `name_value_directive`s this needs to be handled manually,
                     // because it sets a `bool` flag.
                     if let Some(known_bug) =
-                        config.parse_name_value_directive(ln, KNOWN_BUG, testfile, line_number)
+                        config.parse_name_value_directive(ln, KNOWN_BUG, testfile)
                     {
                         let known_bug = known_bug.trim();
                         if known_bug == "unknown"
@@ -632,24 +611,20 @@ impl TestProps {
                         ln,
                         TEST_MIR_PASS,
                         testfile,
-                        line_number,
                         &mut self.mir_unit_test,
                         |s| s.trim().to_string(),
                     );
                     config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
 
                     if let Some(flags) =
-                        config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile, line_number)
+                        config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile)
                     {
                         self.llvm_cov_flags.extend(split_flags(&flags));
                     }
 
-                    if let Some(flags) = config.parse_name_value_directive(
-                        ln,
-                        FILECHECK_FLAGS,
-                        testfile,
-                        line_number,
-                    ) {
+                    if let Some(flags) =
+                        config.parse_name_value_directive(ln, FILECHECK_FLAGS, testfile)
+                    {
                         self.filecheck_flags.extend(split_flags(&flags));
                     }
 
@@ -661,7 +636,6 @@ impl TestProps {
                         ln,
                         directives::CORE_STUBS_COMPILE_FLAGS,
                         testfile,
-                        line_number,
                     ) {
                         let flags = split_flags(&flags);
                         for flag in &flags {
@@ -672,12 +646,9 @@ impl TestProps {
                         self.core_stubs_compile_flags.extend(flags);
                     }
 
-                    if let Some(err_kind) = config.parse_name_value_directive(
-                        ln,
-                        DONT_REQUIRE_ANNOTATIONS,
-                        testfile,
-                        line_number,
-                    ) {
+                    if let Some(err_kind) =
+                        config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS, testfile)
+                    {
                         self.dont_require_annotations
                             .insert(ErrorKind::expect_from_user_str(err_kind.trim()));
                     }
@@ -734,7 +705,7 @@ impl TestProps {
         }
     }
 
-    fn update_fail_mode(&mut self, ln: &str, config: &Config) {
+    fn update_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) {
         let check_ui = |mode: &str| {
             // Mode::Crashes may need build-fail in order to trigger llvm errors or stack overflows
             if config.mode != TestMode::Ui && config.mode != TestMode::Crashes {
@@ -769,7 +740,12 @@ impl TestProps {
         }
     }
 
-    fn update_pass_mode(&mut self, ln: &str, revision: Option<&str>, config: &Config) {
+    fn update_pass_mode(
+        &mut self,
+        ln: &DirectiveLine<'_>,
+        revision: Option<&str>,
+        config: &Config,
+    ) {
         let check_no_run = |s| match (config.mode, s) {
             (TestMode::Ui, _) => (),
             (TestMode::Crashes, _) => (),
@@ -814,7 +790,7 @@ impl TestProps {
         self.pass_mode
     }
 
-    pub fn update_add_core_stubs(&mut self, ln: &str, config: &Config) {
+    fn update_add_core_stubs(&mut self, ln: &DirectiveLine<'_>, config: &Config) {
         let add_core_stubs = config.parse_name_directive(ln, directives::ADD_CORE_STUBS);
         if add_core_stubs {
             if !matches!(config.mode, TestMode::Ui | TestMode::Codegen | TestMode::Assembly) {
@@ -905,10 +881,12 @@ pub(crate) struct CheckDirectiveResult<'ln> {
     trailing_directive: Option<&'ln str>,
 }
 
-pub(crate) fn check_directive<'a>(
-    directive_ln: &'a str,
+fn check_directive<'a>(
+    directive_ln: &DirectiveLine<'a>,
     mode: TestMode,
 ) -> CheckDirectiveResult<'a> {
+    let &DirectiveLine { raw_directive: directive_ln, .. } = directive_ln;
+
     let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, ""));
 
     let is_known_directive = KNOWN_DIRECTIVE_NAMES.contains(&directive_name)
@@ -980,7 +958,7 @@ fn iter_directives(
         // Perform unknown directive check on Rust files.
         if testfile.extension() == Some("rs") {
             let CheckDirectiveResult { is_known_directive, trailing_directive } =
-                check_directive(directive_line.raw_directive, mode);
+                check_directive(&directive_line, mode);
 
             if !is_known_directive {
                 *poisoned = true;
@@ -1014,8 +992,7 @@ impl Config {
     fn parse_and_update_revisions(
         &self,
         testfile: &Utf8Path,
-        line_number: usize,
-        line: &str,
+        line: &DirectiveLine<'_>,
         existing: &mut Vec<String>,
     ) {
         const FORBIDDEN_REVISION_NAMES: [&str; 2] = [
@@ -1028,8 +1005,7 @@ impl Config {
         const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] =
             ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"];
 
-        if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile, line_number)
-        {
+        if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile) {
             if self.mode == TestMode::RunMake {
                 panic!("`run-make` mode tests do not support revisions: {}", testfile);
             }
@@ -1074,13 +1050,8 @@ impl Config {
         (name.to_owned(), value.to_owned())
     }
 
-    fn parse_pp_exact(
-        &self,
-        line: &str,
-        testfile: &Utf8Path,
-        line_number: usize,
-    ) -> Option<Utf8PathBuf> {
-        if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile, line_number) {
+    fn parse_pp_exact(&self, line: &DirectiveLine<'_>, testfile: &Utf8Path) -> Option<Utf8PathBuf> {
+        if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile) {
             Some(Utf8PathBuf::from(&s))
         } else if self.parse_name_directive(line, "pp-exact") {
             testfile.file_name().map(Utf8PathBuf::from)
@@ -1089,7 +1060,9 @@ impl Config {
         }
     }
 
-    fn parse_custom_normalization(&self, raw_directive: &str) -> Option<NormalizeRule> {
+    fn parse_custom_normalization(&self, line: &DirectiveLine<'_>) -> Option<NormalizeRule> {
+        let &DirectiveLine { raw_directive, .. } = line;
+
         // FIXME(Zalathar): Integrate name/value splitting into `DirectiveLine`
         // instead of doing it here.
         let (directive_name, raw_value) = raw_directive.split_once(':')?;
@@ -1110,24 +1083,23 @@ impl Config {
         Some(NormalizeRule { kind, regex, replacement })
     }
 
-    fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
+    fn parse_name_directive(&self, line: &DirectiveLine<'_>, directive: &str) -> bool {
+        let &DirectiveLine { raw_directive: line, .. } = line;
+
         // Ensure the directive is a whole word. Do not match "ignore-x86" when
         // the line says "ignore-x86_64".
         line.starts_with(directive)
             && matches!(line.as_bytes().get(directive.len()), None | Some(&b' ') | Some(&b':'))
     }
 
-    fn parse_negative_name_directive(&self, line: &str, directive: &str) -> bool {
-        line.starts_with("no-") && self.parse_name_directive(&line[3..], directive)
-    }
-
-    pub fn parse_name_value_directive(
+    fn parse_name_value_directive(
         &self,
-        line: &str,
+        line: &DirectiveLine<'_>,
         directive: &str,
         testfile: &Utf8Path,
-        line_number: usize,
     ) -> Option<String> {
+        let &DirectiveLine { line_number, raw_directive: line, .. } = line;
+
         let colon = directive.len();
         if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') {
             let value = line[(colon + 1)..].to_owned();
@@ -1144,52 +1116,37 @@ impl Config {
         }
     }
 
-    fn parse_edition(&self, line: &str, testfile: &Utf8Path, line_number: usize) -> Option<String> {
-        self.parse_name_value_directive(line, "edition", testfile, line_number)
+    fn parse_edition(&self, line: &DirectiveLine<'_>, testfile: &Utf8Path) -> Option<String> {
+        self.parse_name_value_directive(line, "edition", testfile)
     }
 
-    fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) {
-        match value {
-            true => {
-                if self.parse_negative_name_directive(line, directive) {
-                    *value = false;
-                }
-            }
-            false => {
-                if self.parse_name_directive(line, directive) {
-                    *value = true;
-                }
-            }
-        }
+    fn set_name_directive(&self, line: &DirectiveLine<'_>, directive: &str, value: &mut bool) {
+        // If the flag is already true, don't bother looking at the directive.
+        *value = *value || self.parse_name_directive(line, directive);
     }
 
     fn set_name_value_directive<T>(
         &self,
-        line: &str,
+        line: &DirectiveLine<'_>,
         directive: &str,
         testfile: &Utf8Path,
-        line_number: usize,
         value: &mut Option<T>,
         parse: impl FnOnce(String) -> T,
     ) {
         if value.is_none() {
-            *value =
-                self.parse_name_value_directive(line, directive, testfile, line_number).map(parse);
+            *value = self.parse_name_value_directive(line, directive, testfile).map(parse);
         }
     }
 
     fn push_name_value_directive<T>(
         &self,
-        line: &str,
+        line: &DirectiveLine<'_>,
         directive: &str,
         testfile: &Utf8Path,
-        line_number: usize,
         values: &mut Vec<T>,
         parse: impl FnOnce(String) -> T,
     ) {
-        if let Some(value) =
-            self.parse_name_value_directive(line, directive, testfile, line_number).map(parse)
-        {
+        if let Some(value) = self.parse_name_value_directive(line, directive, testfile).map(parse) {
             values.push(value);
         }
     }
@@ -1482,8 +1439,8 @@ pub(crate) fn make_test_description<R: Read>(
         &mut local_poisoned,
         path,
         src,
-        &mut |directive @ DirectiveLine { line_number, raw_directive: ln, .. }| {
-            if !directive.applies_to_test_revision(test_revision) {
+        &mut |ref ln @ DirectiveLine { line_number, .. }| {
+            if !ln.applies_to_test_revision(test_revision) {
                 return;
             }
 
@@ -1507,9 +1464,9 @@ pub(crate) fn make_test_description<R: Read>(
             decision!(cfg::handle_ignore(config, ln));
             decision!(cfg::handle_only(config, ln));
             decision!(needs::handle_needs(&cache.needs, config, ln));
-            decision!(ignore_llvm(config, path, ln, line_number));
-            decision!(ignore_backends(config, path, ln, line_number));
-            decision!(needs_backends(config, path, ln, line_number));
+            decision!(ignore_llvm(config, path, ln));
+            decision!(ignore_backends(config, path, ln));
+            decision!(needs_backends(config, path, ln));
             decision!(ignore_cdb(config, ln));
             decision!(ignore_gdb(config, ln));
             decision!(ignore_lldb(config, ln));
@@ -1549,7 +1506,9 @@ pub(crate) fn make_test_description<R: Read>(
     }
 }
 
-fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {
+fn ignore_cdb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     if config.debugger != Some(Debugger::Cdb) {
         return IgnoreDecision::Continue;
     }
@@ -1572,7 +1531,9 @@ fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
-fn ignore_gdb(config: &Config, line: &str) -> IgnoreDecision {
+fn ignore_gdb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     if config.debugger != Some(Debugger::Gdb) {
         return IgnoreDecision::Continue;
     }
@@ -1620,7 +1581,9 @@ fn ignore_gdb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
-fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
+fn ignore_lldb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     if config.debugger != Some(Debugger::Lldb) {
         return IgnoreDecision::Continue;
     }
@@ -1642,14 +1605,9 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
-fn ignore_backends(
-    config: &Config,
-    path: &Utf8Path,
-    line: &str,
-    line_number: usize,
-) -> IgnoreDecision {
+fn ignore_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision {
     if let Some(backends_to_ignore) =
-        config.parse_name_value_directive(line, "ignore-backends", path, line_number)
+        config.parse_name_value_directive(line, "ignore-backends", path)
     {
         for backend in backends_to_ignore.split_whitespace().map(|backend| {
             match CodegenBackend::try_from(backend) {
@@ -1669,15 +1627,8 @@ fn ignore_backends(
     IgnoreDecision::Continue
 }
 
-fn needs_backends(
-    config: &Config,
-    path: &Utf8Path,
-    line: &str,
-    line_number: usize,
-) -> IgnoreDecision {
-    if let Some(needed_backends) =
-        config.parse_name_value_directive(line, "needs-backends", path, line_number)
-    {
+fn needs_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision {
+    if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends", path) {
         if !needed_backends
             .split_whitespace()
             .map(|backend| match CodegenBackend::try_from(backend) {
@@ -1699,9 +1650,9 @@ fn needs_backends(
     IgnoreDecision::Continue
 }
 
-fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) -> IgnoreDecision {
+fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision {
     if let Some(needed_components) =
-        config.parse_name_value_directive(line, "needs-llvm-components", path, line_number)
+        config.parse_name_value_directive(line, "needs-llvm-components", path)
     {
         let components: HashSet<_> = config.llvm_components.split_whitespace().collect();
         if let Some(missing_component) = needed_components
@@ -1723,7 +1674,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize)
         // Note that these `min` versions will check for not just major versions.
 
         if let Some(version_string) =
-            config.parse_name_value_directive(line, "min-llvm-version", path, line_number)
+            config.parse_name_value_directive(line, "min-llvm-version", path)
         {
             let min_version = extract_llvm_version(&version_string);
             // Ignore if actual version is smaller than the minimum required version.
@@ -1735,7 +1686,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize)
                 };
             }
         } else if let Some(version_string) =
-            config.parse_name_value_directive(line, "max-llvm-major-version", path, line_number)
+            config.parse_name_value_directive(line, "max-llvm-major-version", path)
         {
             let max_version = extract_llvm_version(&version_string);
             // Ignore if actual major version is larger than the maximum required major version.
@@ -1749,7 +1700,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize)
                 };
             }
         } else if let Some(version_string) =
-            config.parse_name_value_directive(line, "min-system-llvm-version", path, line_number)
+            config.parse_name_value_directive(line, "min-system-llvm-version", path)
         {
             let min_version = extract_llvm_version(&version_string);
             // Ignore if using system LLVM and actual version
@@ -1762,7 +1713,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize)
                 };
             }
         } else if let Some(version_range) =
-            config.parse_name_value_directive(line, "ignore-llvm-version", path, line_number)
+            config.parse_name_value_directive(line, "ignore-llvm-version", path)
         {
             // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
             let (v_min, v_max) =
@@ -1788,7 +1739,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize)
                 }
             }
         } else if let Some(version_string) =
-            config.parse_name_value_directive(line, "exact-llvm-major-version", path, line_number)
+            config.parse_name_value_directive(line, "exact-llvm-major-version", path)
         {
             // Syntax is "exact-llvm-major-version: <version>"
             let version = extract_llvm_version(&version_string);
diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs
index 7c1ed2e7006..0675a6feac3 100644
--- a/src/tools/compiletest/src/directives/auxiliary.rs
+++ b/src/tools/compiletest/src/directives/auxiliary.rs
@@ -7,6 +7,7 @@ use camino::Utf8Path;
 
 use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
 use crate::common::Config;
+use crate::directives::DirectiveLine;
 
 /// Properties parsed from `aux-*` test directives.
 #[derive(Clone, Debug, Default)]
@@ -45,40 +46,28 @@ impl AuxProps {
 /// and update [`AuxProps`] accordingly.
 pub(super) fn parse_and_update_aux(
     config: &Config,
-    ln: &str,
+    directive_line: &DirectiveLine<'_>,
     testfile: &Utf8Path,
-    line_number: usize,
     aux: &mut AuxProps,
 ) {
+    let &DirectiveLine { raw_directive: ln, .. } = directive_line;
+
     if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) {
         return;
     }
 
-    config.push_name_value_directive(ln, AUX_BUILD, testfile, line_number, &mut aux.builds, |r| {
+    let ln = directive_line;
+
+    config.push_name_value_directive(ln, AUX_BUILD, testfile, &mut aux.builds, |r| {
         r.trim().to_string()
     });
-    config.push_name_value_directive(ln, AUX_BIN, testfile, line_number, &mut aux.bins, |r| {
+    config
+        .push_name_value_directive(ln, AUX_BIN, testfile, &mut aux.bins, |r| r.trim().to_string());
+    config.push_name_value_directive(ln, AUX_CRATE, testfile, &mut aux.crates, parse_aux_crate);
+    config.push_name_value_directive(ln, PROC_MACRO, testfile, &mut aux.proc_macros, |r| {
         r.trim().to_string()
     });
-    config.push_name_value_directive(
-        ln,
-        AUX_CRATE,
-        testfile,
-        line_number,
-        &mut aux.crates,
-        parse_aux_crate,
-    );
-    config.push_name_value_directive(
-        ln,
-        PROC_MACRO,
-        testfile,
-        line_number,
-        &mut aux.proc_macros,
-        |r| r.trim().to_string(),
-    );
-    if let Some(r) =
-        config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile, line_number)
-    {
+    if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile) {
         aux.codegen_backend = Some(r.trim().to_owned());
     }
 }
diff --git a/src/tools/compiletest/src/directives/cfg.rs b/src/tools/compiletest/src/directives/cfg.rs
index 802a1d63d1f..62a4b88a33a 100644
--- a/src/tools/compiletest/src/directives/cfg.rs
+++ b/src/tools/compiletest/src/directives/cfg.rs
@@ -1,12 +1,14 @@
 use std::collections::HashSet;
 
 use crate::common::{CompareMode, Config, Debugger};
-use crate::directives::IgnoreDecision;
+use crate::directives::{DirectiveLine, IgnoreDecision};
 
 const EXTRA_ARCHS: &[&str] = &["spirv"];
 
-pub(super) fn handle_ignore(config: &Config, line: &str) -> IgnoreDecision {
+pub(super) fn handle_ignore(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
     let parsed = parse_cfg_name_directive(config, line, "ignore");
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     match parsed.outcome {
         MatchOutcome::NoMatch => IgnoreDecision::Continue,
         MatchOutcome::Match => IgnoreDecision::Ignore {
@@ -21,8 +23,10 @@ pub(super) fn handle_ignore(config: &Config, line: &str) -> IgnoreDecision {
     }
 }
 
-pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision {
+pub(super) fn handle_only(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision {
     let parsed = parse_cfg_name_directive(config, line, "only");
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     match parsed.outcome {
         MatchOutcome::Match => IgnoreDecision::Continue,
         MatchOutcome::NoMatch => IgnoreDecision::Ignore {
@@ -43,9 +47,11 @@ pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision {
 /// or `only-windows`.
 fn parse_cfg_name_directive<'a>(
     config: &Config,
-    line: &'a str,
+    line: &'a DirectiveLine<'a>,
     prefix: &str,
 ) -> ParsedNameDirective<'a> {
+    let &DirectiveLine { raw_directive: line, .. } = line;
+
     if !line.as_bytes().starts_with(prefix.as_bytes()) {
         return ParsedNameDirective::not_a_directive();
     }
diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs
index 3b7a9478717..c8a729d8aab 100644
--- a/src/tools/compiletest/src/directives/needs.rs
+++ b/src/tools/compiletest/src/directives/needs.rs
@@ -1,10 +1,10 @@
 use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer};
-use crate::directives::{IgnoreDecision, llvm_has_libzstd};
+use crate::directives::{DirectiveLine, IgnoreDecision, llvm_has_libzstd};
 
 pub(super) fn handle_needs(
     cache: &CachedNeedsConditions,
     config: &Config,
-    ln: &str,
+    ln: &DirectiveLine<'_>,
 ) -> IgnoreDecision {
     // Note that we intentionally still put the needs- prefix here to make the file show up when
     // grepping for a directive name, even though we could technically strip that.
@@ -181,6 +181,8 @@ pub(super) fn handle_needs(
         },
     ];
 
+    let &DirectiveLine { raw_directive: ln, .. } = ln;
+
     let (name, rest) = match ln.split_once([':', ' ']) {
         Some((name, rest)) => (name, Some(rest)),
         None => (ln, None),
diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs
index ba824124e87..3d439e98eb7 100644
--- a/src/tools/compiletest/src/runtest/debugger.rs
+++ b/src/tools/compiletest/src/runtest/debugger.rs
@@ -4,7 +4,6 @@ use std::io::{BufRead, BufReader};
 
 use camino::{Utf8Path, Utf8PathBuf};
 
-use crate::common::Config;
 use crate::runtest::ProcRes;
 
 /// Representation of information to invoke a debugger and check its output
@@ -20,11 +19,7 @@ pub(super) struct DebuggerCommands {
 }
 
 impl DebuggerCommands {
-    pub fn parse_from(
-        file: &Utf8Path,
-        config: &Config,
-        debugger_prefix: &str,
-    ) -> Result<Self, String> {
+    pub fn parse_from(file: &Utf8Path, debugger_prefix: &str) -> Result<Self, String> {
         let command_directive = format!("{debugger_prefix}-command");
         let check_directive = format!("{debugger_prefix}-check");
 
@@ -47,14 +42,10 @@ impl DebuggerCommands {
                 continue;
             };
 
-            if let Some(command) =
-                config.parse_name_value_directive(&line, &command_directive, file, line_no)
-            {
+            if let Some(command) = parse_name_value(&line, &command_directive) {
                 commands.push(command);
             }
-            if let Some(pattern) =
-                config.parse_name_value_directive(&line, &check_directive, file, line_no)
-            {
+            if let Some(pattern) = parse_name_value(&line, &check_directive) {
                 check_lines.push((line_no, pattern));
             }
         }
@@ -114,6 +105,18 @@ impl DebuggerCommands {
     }
 }
 
+/// Split off from the main `parse_name_value_directive`, so that improvements
+/// to directive handling aren't held back by debuginfo test commands.
+fn parse_name_value(line: &str, name: &str) -> Option<String> {
+    if let Some(after_name) = line.strip_prefix(name)
+        && let Some(value) = after_name.strip_prefix(':')
+    {
+        Some(value.to_owned())
+    } else {
+        None
+    }
+}
+
 /// Check that the pattern in `check_line` applies to `line`. Returns `true` if they do match.
 fn check_single_line(line: &str, check_line: &str) -> bool {
     // Allow check lines to leave parts unspecified (e.g., uninitialized
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index 071c0863b7e..9175a38ffa5 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -59,7 +59,7 @@ impl TestCx<'_> {
         }
 
         // Parse debugger commands etc from test files
-        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "cdb")
+        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "cdb")
             .unwrap_or_else(|e| self.fatal(&e));
 
         // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands
@@ -130,7 +130,7 @@ impl TestCx<'_> {
     }
 
     fn run_debuginfo_gdb_test_no_opt(&self) {
-        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "gdb")
+        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "gdb")
             .unwrap_or_else(|e| self.fatal(&e));
         let mut cmds = dbg_cmds.commands.join("\n");
 
@@ -397,7 +397,7 @@ impl TestCx<'_> {
         }
 
         // Parse debugger commands etc from test files
-        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "lldb")
+        let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "lldb")
             .unwrap_or_else(|e| self.fatal(&e));
 
         // Write debugger script:
diff --git a/tests/codegen-llvm/autodiff/abi_handling.rs b/tests/codegen-llvm/autodiff/abi_handling.rs
index 454ec698b91..5c8126898a8 100644
--- a/tests/codegen-llvm/autodiff/abi_handling.rs
+++ b/tests/codegen-llvm/autodiff/abi_handling.rs
@@ -1,7 +1,7 @@
 //@ revisions: debug release
 
-//@[debug] compile-flags: -Zautodiff=Enable -C opt-level=0 -Clto=fat
-//@[release] compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat
+//@[debug] compile-flags: -Zautodiff=Enable,NoTT -C opt-level=0 -Clto=fat
+//@[release] compile-flags: -Zautodiff=Enable,NoTT -C opt-level=3 -Clto=fat
 //@ no-prefer-dynamic
 //@ needs-enzyme
 
diff --git a/tests/codegen-llvm/autodiff/batched.rs b/tests/codegen-llvm/autodiff/batched.rs
index 306a6ed9d1f..dc82403212f 100644
--- a/tests/codegen-llvm/autodiff/batched.rs
+++ b/tests/codegen-llvm/autodiff/batched.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zautodiff=Enable -C opt-level=3  -Clto=fat
+//@ compile-flags: -Zautodiff=Enable,NoTT -C opt-level=3  -Clto=fat
 //@ no-prefer-dynamic
 //@ needs-enzyme
 //
diff --git a/tests/codegen-llvm/autodiff/scalar.rs b/tests/codegen-llvm/autodiff/scalar.rs
index 55b989f920d..53672a89230 100644
--- a/tests/codegen-llvm/autodiff/scalar.rs
+++ b/tests/codegen-llvm/autodiff/scalar.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zautodiff=Enable -C opt-level=3  -Clto=fat
+//@ compile-flags: -Zautodiff=Enable,NoTT -C opt-level=3  -Clto=fat
 //@ no-prefer-dynamic
 //@ needs-enzyme
 #![feature(autodiff)]
diff --git a/tests/codegen-llvm/autodiff/sret.rs b/tests/codegen-llvm/autodiff/sret.rs
index dbc253ce894..498cd3fea01 100644
--- a/tests/codegen-llvm/autodiff/sret.rs
+++ b/tests/codegen-llvm/autodiff/sret.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zautodiff=Enable -C opt-level=3  -Clto=fat
+//@ compile-flags: -Zautodiff=Enable,NoTT -C opt-level=3  -Clto=fat
 //@ no-prefer-dynamic
 //@ needs-enzyme
 
diff --git a/tests/codegen-llvm/autodiff/void_ret.rs b/tests/codegen-llvm/autodiff/void_ret.rs
new file mode 100644
index 00000000000..98c6b98eef4
--- /dev/null
+++ b/tests/codegen-llvm/autodiff/void_ret.rs
@@ -0,0 +1,41 @@
+//@ compile-flags: -Zautodiff=Enable,NoTT,NoPostopt -C no-prepopulate-passes -C opt-level=3  -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+
+#![feature(autodiff)]
+use std::autodiff::*;
+
+// Usually we would store the return value of the differentiated function.
+// However, if the return type is void or an empty struct,
+// we don't need to store anything. Verify this, since it caused a bug.
+
+// CHECK:; void_ret::main
+// CHECK-NEXT:    ; Function Attrs:
+// CHECK-NEXT:    define internal
+// CHECK-NOT: store {} undef, ptr undef
+// CHECK: ret void
+
+#[autodiff_reverse(bar, Duplicated, Duplicated)]
+pub fn foo(r: &[f64; 10], res: &mut f64) {
+    let mut output = [0.0; 10];
+    output[0] = r[0];
+    output[1] = r[1] * r[2];
+    output[2] = r[4] * r[5];
+    output[3] = r[2] * r[6];
+    output[4] = r[1] * r[7];
+    output[5] = r[2] * r[8];
+    output[6] = r[1] * r[9];
+    output[7] = r[5] * r[6];
+    output[8] = r[5] * r[7];
+    output[9] = r[4] * r[8];
+    *res = output.iter().sum();
+}
+fn main() {
+    let inputs = Box::new([3.1; 10]);
+    let mut d_inputs = Box::new([0.0; 10]);
+    let mut res = Box::new(0.0);
+    let mut d_res = Box::new(1.0);
+
+    bar(&inputs, &mut d_inputs, &mut res, &mut d_res);
+    dbg!(&d_inputs);
+}
diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
index df5f29e35fe..86f2d5f5954 100644
--- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
+++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
@@ -2,7 +2,6 @@
 // Testing that a librustc_ast can parse modules with canonicalized base path
 //@ ignore-cross-compile
 //@ ignore-remote
-// no-remap-src-base: Reading `file!()` (expectedly) fails when enabled.
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.rs
index 5fa5b74c0c0..0a0dca804ef 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.rs
@@ -1,5 +1,6 @@
 //@ add-core-stubs
-//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Cincremental=true
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ incremental (required to trigger the bug)
 //@ needs-llvm-components: arm
 #![feature(abi_cmse_nonsecure_call, no_core)]
 #![no_core]
@@ -8,7 +9,7 @@ extern crate minicore;
 use minicore::*;
 
 // A regression test for https://github.com/rust-lang/rust/issues/131639.
-// NOTE: -Cincremental=true was required for triggering the bug.
+// NOTE: `-Cincremental` was required for triggering the bug.
 
 fn foo() {
     id::<extern "cmse-nonsecure-call" fn(&'a ())>(PhantomData);
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.stderr
index 4aca17e7354..7300bdb72cd 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/undeclared-lifetime.stderr
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/undeclared-lifetime.rs:14:43
+  --> $DIR/undeclared-lifetime.rs:15:43
    |
 LL |     id::<extern "cmse-nonsecure-call" fn(&'a ())>(PhantomData);
    |                                           ^^ undeclared lifetime
diff --git a/tests/ui/errors/auxiliary/remapped_dep.rs b/tests/ui/errors/auxiliary/remapped_dep.rs
index 36d4699a306..997118f822c 100644
--- a/tests/ui/errors/auxiliary/remapped_dep.rs
+++ b/tests/ui/errors/auxiliary/remapped_dep.rs
@@ -1,4 +1,4 @@
 //@ compile-flags: --remap-path-prefix={{src-base}}/errors/auxiliary=remapped-aux
-// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file.
+// Manually remap, so the remapped path remains in .stderr file.
 
 pub struct SomeStruct {} // This line should be show as part of the error.
diff --git a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr
index b4f83f6bfc0..b2651f3e03a 100644
--- a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr
+++ b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr
@@ -1,5 +1,5 @@
 error[E0423]: expected value, found struct `remapped_dep::SomeStruct`
-  --> $DIR/remap-path-prefix-reverse.rs:16:13
+  --> $DIR/remap-path-prefix-reverse.rs:15:13
    |
 LL |     let _ = remapped_dep::SomeStruct;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}`
diff --git a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr
index b4f83f6bfc0..b2651f3e03a 100644
--- a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr
+++ b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr
@@ -1,5 +1,5 @@
 error[E0423]: expected value, found struct `remapped_dep::SomeStruct`
-  --> $DIR/remap-path-prefix-reverse.rs:16:13
+  --> $DIR/remap-path-prefix-reverse.rs:15:13
    |
 LL |     let _ = remapped_dep::SomeStruct;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}`
diff --git a/tests/ui/errors/remap-path-prefix-reverse.rs b/tests/ui/errors/remap-path-prefix-reverse.rs
index 28fdabb8f4d..562e44690f7 100644
--- a/tests/ui/errors/remap-path-prefix-reverse.rs
+++ b/tests/ui/errors/remap-path-prefix-reverse.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: --remap-path-prefix={{src-base}}/errors/auxiliary=remapped-aux
 
 //@ revisions: local-self remapped-self
-// [local-self] no-remap-src-base: The hack should work regardless of remapping.
 //@ [remapped-self] remap-src-base
 
 // Verify that the expected source code is shown.
diff --git a/tests/ui/errors/remap-path-prefix.rs b/tests/ui/errors/remap-path-prefix.rs
index 7e38e16280f..de18aa8cc20 100644
--- a/tests/ui/errors/remap-path-prefix.rs
+++ b/tests/ui/errors/remap-path-prefix.rs
@@ -2,7 +2,7 @@
 //@ compile-flags: --remap-path-prefix={{src-base}}=remapped
 //@ [with-diagnostic-scope]compile-flags: -Zremap-path-scope=diagnostics
 //@ [without-diagnostic-scope]compile-flags: -Zremap-path-scope=object
-// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file.
+// Manually remap, so the remapped path remains in .stderr file.
 
 // The remapped paths are not normalized by compiletest.
 //@ normalize-stderr: "\\(errors)" -> "/$1"
diff --git a/tests/ui/indexing/ambiguity-after-deref-step.rs b/tests/ui/indexing/ambiguity-after-deref-step.rs
new file mode 100644
index 00000000000..2dd95eed097
--- /dev/null
+++ b/tests/ui/indexing/ambiguity-after-deref-step.rs
@@ -0,0 +1,9 @@
+// Regression test making sure that indexing fails with an ambiguity
+// error if one of the deref-steps encounters an inference variable.
+
+fn main() {
+    let x = &Default::default();
+    //~^ ERROR type annotations needed for `&_`
+    x[1];
+    let _: &Vec<()> = x;
+}
diff --git a/tests/ui/indexing/ambiguity-after-deref-step.stderr b/tests/ui/indexing/ambiguity-after-deref-step.stderr
new file mode 100644
index 00000000000..c7ddd4731c7
--- /dev/null
+++ b/tests/ui/indexing/ambiguity-after-deref-step.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `&_`
+  --> $DIR/ambiguity-after-deref-step.rs:5:9
+   |
+LL |     let x = &Default::default();
+   |         ^
+LL |
+LL |     x[1];
+   |     - type must be known at this point
+   |
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
+   |
+LL |     let x: &_ = &Default::default();
+   |          ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/methods/overflow-if-subtyping.rs b/tests/ui/methods/overflow-if-subtyping.rs
new file mode 100644
index 00000000000..a97f29f1f6d
--- /dev/null
+++ b/tests/ui/methods/overflow-if-subtyping.rs
@@ -0,0 +1,30 @@
+//@ check-pass
+
+// Regression test for #128887.
+#![allow(unconditional_recursion)]
+trait Mappable<T> {
+    type Output;
+}
+
+trait Bound<T> {}
+// Deleting this impl made it compile on beta
+impl<T> Bound<T> for T {}
+
+trait Generic<M> {}
+
+// Deleting the `: Mappable<T>` already made it error on stable.
+struct IndexWithIter<I, M: Mappable<T>, T>(I, M, T);
+
+impl<I, M, T> IndexWithIter<I, M, T>
+where
+    <M as Mappable<T>>::Output: Bound<T>,
+    // Flipping these where bounds causes this to succeed, even when removing
+    // the where-clause on the struct definition.
+    M: Mappable<T>,
+    I: Generic<M>,
+{
+    fn new(x: I) {
+        IndexWithIter::<_, _, _>::new(x);
+    }
+}
+fn main() {}
diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs
index 1e058abe3bc..c3dddd8e459 100644
--- a/tests/ui/proc-macro/expand-expr.rs
+++ b/tests/ui/proc-macro/expand-expr.rs
@@ -1,6 +1,6 @@
 //@ proc-macro: expand-expr.rs
 //@ ignore-backends: gcc
-// no-remap-src-base: check_expand_expr_file!() fails when enabled.
+// No `remap-src-base`, since `check_expand_expr_file!()` fails when enabled.
 
 #![feature(concat_bytes)]
 extern crate expand_expr;
diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs
index 70f0d5f6ea9..08e26c81142 100644
--- a/tests/ui/proc-macro/pretty-print-hack-show.rs
+++ b/tests/ui/proc-macro/pretty-print-hack-show.rs
@@ -1,7 +1,6 @@
 //@ proc-macro: test-macros.rs
 //@ compile-flags: -Z span-debug
 //@ revisions: local remapped
-// [local] no-remap-src-base: The hack should work regardless of remapping.
 //@ [remapped] remap-src-base
 
 #![no_std] // Don't load unnecessary hygiene information from std
diff --git a/tests/ui/traits/next-solver/forced-ambiguity-typenum-ice.rs b/tests/ui/traits/next-solver/forced-ambiguity-typenum-ice.rs
new file mode 100644
index 00000000000..679d6b1fb16
--- /dev/null
+++ b/tests/ui/traits/next-solver/forced-ambiguity-typenum-ice.rs
@@ -0,0 +1,60 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#105. We previously encountered
+// an ICE in typenum as `forced_ambiguity` failed. While this test no longer causes
+// `forced_ambiguity` to error, we still want to use it as a regression test.
+
+pub struct UInt<U, B> {
+    _msb: U,
+    _lsb: B,
+}
+pub struct B1;
+pub trait Sub<Rhs> {
+    type Output;
+}
+impl<U, B> Sub<B1> for UInt<UInt<U, B>, B1> {
+    type Output = ();
+}
+impl<U> Sub<B1> for UInt<U, ()>
+where
+    U: Sub<B1>,
+    U::Output: Send,
+{
+    type Output = ();
+}
+
+pub trait Op<N, R, I> {
+    fn op(&self) {
+        unimplemented!()
+    }
+}
+trait OpIf<N, R, I> {}
+
+impl<N, Ur, Br, I> Op<N, UInt<Ur, Br>, I> for ()
+where
+    N: Sub<I>,
+    (): OpIf<N, UInt<UInt<Ur, Br>, N::Output>, I>,
+{
+}
+impl<N, R, Ui, Bi> OpIf<N, R, UInt<Ui, Bi>> for ()
+where
+    UInt<Ui, Bi>: Sub<B1>,
+    (): Op<N, R, <UInt<Ui, Bi> as Sub<B1>>::Output>,
+{
+}
+impl<N, R> OpIf<N, R, ()> for () where R: Sub<N> {}
+
+pub trait Compute {
+    type Output;
+}
+
+pub fn repro<Ul, Bl>()
+where
+    UInt<Ul, Bl>: Compute,
+    <UInt<Ul, Bl> as Compute>::Output: Sub<B1>,
+    (): Op<UInt<(), Bl>, (), ()>,
+{
+    ().op();
+}
+fn main() {}