From b7297ac4407e25f7872cd061246196cd4c8b485b Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 29 Sep 2024 13:08:48 -0400
Subject: [PATCH 1/4] Add gate for precise capturing in traits

---
 compiler/rustc_ast_lowering/src/lib.rs        | 19 ++++++++++++++-----
 compiler/rustc_feature/src/unstable.rs        |  2 ++
 compiler/rustc_span/src/symbol.rs             |  1 +
 ...eature-gate-precise_capturing_in_traits.rs |  6 ++++++
 ...re-gate-precise_capturing_in_traits.stderr | 13 +++++++++++++
 .../forgot-to-capture-type.stderr             |  3 +++
 .../precise-capturing/redundant.rpitit.stderr |  6 ++++++
 ...itit-captures-more-method-lifetimes.stderr |  3 +++
 .../precise-capturing/rpitit.stderr           |  3 +++
 .../precise-capturing/self-capture.stderr     |  3 +++
 10 files changed, 54 insertions(+), 5 deletions(-)
 create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs
 create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr

diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index b26797f42032f..35af4d63cc760 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1573,11 +1573,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Feature gate for RPITIT + use<..>
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
-                if let Some(span) = bounds.iter().find_map(|bound| match *bound {
-                    ast::GenericBound::Use(_, span) => Some(span),
-                    _ => None,
-                }) {
-                    self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
+                if !self.tcx.features().precise_capturing_in_traits
+                    && let Some(span) = bounds.iter().find_map(|bound| match *bound {
+                        ast::GenericBound::Use(_, span) => Some(span),
+                        _ => None,
+                    })
+                {
+                    let mut diag =
+                        self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span });
+                    add_feature_diagnostics(
+                        &mut diag,
+                        self.tcx.sess,
+                        sym::precise_capturing_in_traits,
+                    );
+                    diag.emit();
                 }
             }
             _ => {}
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 380e36fe40566..19a6960cf4d88 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -565,6 +565,8 @@ declare_features! (
     (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
+    /// Allows `use<..>` precise capturign on impl Trait in traits.
+    (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1527600e764c0..683f59a89995e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1479,6 +1479,7 @@ symbols! {
         powif64,
         pre_dash_lto: "pre-lto",
         precise_capturing,
+        precise_capturing_in_traits,
         precise_pointer_size_matching,
         pref_align_of,
         prefetch_read_data,
diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs
new file mode 100644
index 0000000000000..308b41dfc68ab
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs
@@ -0,0 +1,6 @@
+trait Foo {
+    fn test() -> impl Sized + use<Self>;
+    //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr
new file mode 100644
index 0000000000000..b2c6bf61124d9
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr
@@ -0,0 +1,13 @@
+error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
+  --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31
+   |
+LL |     fn test() -> impl Sized + use<Self>;
+   |                               ^^^^^^^^^
+   |
+   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
index d9be9d543e450..23d6a3bd11e82 100644
--- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
@@ -5,6 +5,9 @@ LL |     fn bar() -> impl Sized + use<>;
    |                              ^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: `impl Trait` must mention all type parameters in scope in `use<...>`
   --> $DIR/forgot-to-capture-type.rs:1:23
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
index 213888356e572..27f8ff92d3e65 100644
--- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
@@ -5,6 +5,9 @@ LL |     fn in_trait() -> impl Sized + use<'a, Self>;
    |                                   ^^^^^^^^^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
   --> $DIR/redundant.rs:21:35
@@ -13,6 +16,9 @@ LL |     fn in_trait() -> impl Sized + use<'a> {}
    |                                   ^^^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
index b390a23eef414..ffd9646a4038b 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
@@ -5,6 +5,9 @@ LL |     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
    |                                                     ^^^^^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: return type captures more lifetimes than trait definition
   --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
index 5a120df9f047a..c162875f327cc 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
@@ -5,6 +5,9 @@ LL |     fn hello() -> impl PartialEq + use<Self>;
    |                                    ^^^^^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
   --> $DIR/rpitit.rs:9:19
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr
index c1974600f30c5..45ebc429d88a7 100644
--- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr
+++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr
@@ -5,6 +5,9 @@ LL |     fn bar<'a>() -> impl Sized + use<Self>;
    |                                  ^^^^^^^^^
    |
    = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
+   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
+   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
 

From a7dc98733da8b84cfc21a538541a41803c4529a0 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 29 Sep 2024 13:41:13 -0400
Subject: [PATCH 2/4] Add variances to RPITITs

---
 .../rustc_hir_analysis/src/variance/mod.rs    | 49 +++++++++++++--
 compiler/rustc_metadata/src/rmeta/encoder.rs  |  5 +-
 compiler/rustc_middle/src/ty/context.rs       |  4 ++
 compiler/rustc_type_ir/src/interner.rs        |  2 +
 compiler/rustc_type_ir/src/relate.rs          | 10 ++++
 tests/ui/impl-trait/in-trait/variance.rs      | 23 ++++----
 tests/ui/impl-trait/in-trait/variance.stderr  | 34 +++++++----
 .../forgot-to-capture-type.rs                 |  3 +-
 .../forgot-to-capture-type.stderr             | 17 +-----
 .../precise-capturing/redundant.normal.stderr | 20 -------
 .../precise-capturing/redundant.rpitit.stderr | 24 --------
 .../impl-trait/precise-capturing/redundant.rs | 15 +++--
 .../precise-capturing/redundant.stderr        | 36 +++++++++++
 .../rpitit-captures-more-method-lifetimes.rs  |  5 +-
 ...itit-captures-more-method-lifetimes.stderr | 23 ++------
 .../rpitit-impl-captures-too-much.rs          | 14 +++++
 .../rpitit-impl-captures-too-much.stderr      | 17 ++++++
 .../ui/impl-trait/precise-capturing/rpitit.rs | 31 +++++++---
 .../precise-capturing/rpitit.stderr           | 59 ++++++++-----------
 .../precise-capturing/self-capture.rs         |  5 +-
 .../precise-capturing/self-capture.stderr     | 13 ----
 21 files changed, 241 insertions(+), 168 deletions(-)
 delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.normal.stderr
 delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
 create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.stderr
 create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
 create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
 delete mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr

diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 12bb9a3f9e0f3..02cfb57b836f6 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -5,6 +5,7 @@
 
 use itertools::Itertools;
 use rustc_arena::DroplessArena;
+use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
@@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
             let crate_map = tcx.crate_variances(());
             return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
         }
+        DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
+            Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+                return variance_of_opaque(
+                    tcx,
+                    opaque_def_id.expect_local(),
+                    ForceCaptureTraitArgs::Yes,
+                );
+            }
+            None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
+        },
         DefKind::OpaqueTy => {
-            return variance_of_opaque(tcx, item_def_id);
+            let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn {
+                parent: _,
+                in_trait_or_impl: Some(hir::RpitContext::Trait),
+            } =
+                tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin
+            {
+                ForceCaptureTraitArgs::Yes
+            } else {
+                ForceCaptureTraitArgs::No
+            };
+
+            return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
         }
         _ => {}
     }
@@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
     span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
 }
 
+#[derive(Debug, Copy, Clone)]
+enum ForceCaptureTraitArgs {
+    Yes,
+    No,
+}
+
 #[instrument(level = "trace", skip(tcx), ret)]
-fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
+fn variance_of_opaque(
+    tcx: TyCtxt<'_>,
+    item_def_id: LocalDefId,
+    force_capture_trait_args: ForceCaptureTraitArgs,
+) -> &[ty::Variance] {
     let generics = tcx.generics_of(item_def_id);
 
     // Opaque types may only use regions that are bound. So for
@@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) {
             match t.kind() {
-                ty::Alias(_, ty::AliasTy { def_id, args, .. })
-                    if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
-                {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
                     self.visit_opaque(*def_id, args);
                 }
                 _ => t.super_visit_with(self),
@@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         let mut generics = generics;
         while let Some(def_id) = generics.parent {
             generics = tcx.generics_of(def_id);
+
+            // Don't mark trait params generic if we're in an RPITIT.
+            if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
+                && generics.parent.is_none()
+            {
+                debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+                break;
+            }
+
             for param in &generics.own_params {
                 match param.kind {
                     ty::GenericParamDefKind::Lifetime => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 610c682d3a461..afe03531861c9 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
         | DefKind::Fn
         | DefKind::Ctor(..)
         | DefKind::AssocFn => true,
+        DefKind::AssocTy => {
+            // Only encode variances for RPITITs (for traits)
+            matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. }))
+        }
         DefKind::Mod
         | DefKind::Field
-        | DefKind::AssocTy
         | DefKind::AssocConst
         | DefKind::TyParam
         | DefKind::ConstParam
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 90265f67bc1f6..590e1d336f340 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.trait_def(trait_def_id).implement_via_object
     }
 
+    fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
+        self.is_impl_trait_in_trait(def_id)
+    }
+
     fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed {
         self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string())
     }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index a72e7b482a6fd..f06017d7e5c35 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -261,6 +261,8 @@ pub trait Interner:
 
     fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
 
+    fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
+
     fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
 
     fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool;
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index 1302906adab1f..e1f3e493e36e3 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -254,6 +254,16 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
                     b.args,
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
                 )?,
+                ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => {
+                    relate_args_with_variances(
+                        relation,
+                        a.def_id,
+                        relation.cx().variances_of(a.def_id),
+                        a.args,
+                        b.args,
+                        false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                    )?
+                }
                 ty::Projection | ty::Weak | ty::Inherent => {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }
diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs
index 0ac44bf7546c2..19905c608e3b5 100644
--- a/tests/ui/impl-trait/in-trait/variance.rs
+++ b/tests/ui/impl-trait/in-trait/variance.rs
@@ -1,22 +1,25 @@
-#![feature(rustc_attrs)]
+#![feature(rustc_attrs, precise_capturing_in_traits)]
 #![allow(internal_features)]
 #![rustc_variance_of_opaques]
 
-trait Captures<'a> {}
-impl<T> Captures<'_> for T {}
-
 trait Foo<'i> {
     fn implicit_capture_early<'a: 'a>() -> impl Sized {}
-    //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
+    //~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
+
+    fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
+    //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
 
-    fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {}
-    //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
+    fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
+    //~^ [Self: o, 'i: o, 'a: *, 'i: o]
 
     fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
-    //~^ [Self: o, 'i: *, 'a: o, 'i: o]
+    //~^ [Self: o, 'i: o, 'a: o, 'i: o]
+
+    fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
+    //~^ [Self: o, 'i: o, 'i: o, 'a: o]
 
-    fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
-    //~^ [Self: o, 'i: *, 'a: o, 'i: o]
+    fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
+    //~^ [Self: o, 'i: o, 'i: o]
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr
index 54e0afbaa950d..f65174e1c358c 100644
--- a/tests/ui/impl-trait/in-trait/variance.stderr
+++ b/tests/ui/impl-trait/in-trait/variance.stderr
@@ -1,26 +1,38 @@
-error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
-  --> $DIR/variance.rs:9:44
+error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
+  --> $DIR/variance.rs:6:44
    |
 LL |     fn implicit_capture_early<'a: 'a>() -> impl Sized {}
    |                                            ^^^^^^^^^^
 
-error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o]
-  --> $DIR/variance.rs:12:44
+error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
+  --> $DIR/variance.rs:9:44
+   |
+LL |     fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [Self: o, 'i: o, 'a: *, 'i: o]
+  --> $DIR/variance.rs:12:40
    |
-LL |     fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {}
-   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [Self: o, 'i: *, 'a: o, 'i: o]
+error: [Self: o, 'i: o, 'a: o, 'i: o]
   --> $DIR/variance.rs:15:48
    |
 LL |     fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
    |                                                ^^^^^^^^^^
 
-error: [Self: o, 'i: *, 'a: o, 'i: o]
+error: [Self: o, 'i: o, 'i: o, 'a: o]
   --> $DIR/variance.rs:18:48
    |
-LL |     fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
-   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [Self: o, 'i: o, 'i: o]
+  --> $DIR/variance.rs:21:44
+   |
+LL |     fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
index 9d68819f657db..6c2477c9744ab 100644
--- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs
@@ -1,10 +1,11 @@
+#![feature(precise_capturing_in_traits)]
+
 fn type_param<T>() -> impl Sized + use<> {}
 //~^ ERROR `impl Trait` must mention all type parameters in scope
 
 trait Foo {
     fn bar() -> impl Sized + use<>;
     //~^ ERROR `impl Trait` must mention the `Self` type of the trait
-    //~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
index 23d6a3bd11e82..93b44a0c18c27 100644
--- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
+++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr
@@ -1,16 +1,5 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/forgot-to-capture-type.rs:5:30
-   |
-LL |     fn bar() -> impl Sized + use<>;
-   |                              ^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error: `impl Trait` must mention all type parameters in scope in `use<...>`
-  --> $DIR/forgot-to-capture-type.rs:1:23
+  --> $DIR/forgot-to-capture-type.rs:3:23
    |
 LL | fn type_param<T>() -> impl Sized + use<> {}
    |               -       ^^^^^^^^^^^^^^^^^^
@@ -20,7 +9,7 @@ LL | fn type_param<T>() -> impl Sized + use<> {}
    = note: currently, all type parameters are required to be mentioned in the precise captures list
 
 error: `impl Trait` must mention the `Self` type of the trait in `use<...>`
-  --> $DIR/forgot-to-capture-type.rs:5:17
+  --> $DIR/forgot-to-capture-type.rs:7:17
    |
 LL | trait Foo {
    | --------- `Self` type parameter is implicitly captured by this `impl Trait`
@@ -29,5 +18,5 @@ LL |     fn bar() -> impl Sized + use<>;
    |
    = note: currently, all type parameters are required to be mentioned in the precise captures list
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr
deleted file mode 100644
index d1bcbaa33ae2b..0000000000000
--- a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:5:19
-   |
-LL | fn hello<'a>() -> impl Sized + use<'a> {}
-   |                   ^^^^^^^^^^^^^-------
-   |                                |
-   |                                help: remove the `use<...>` syntax
-   |
-   = note: `#[warn(impl_trait_redundant_captures)]` on by default
-
-warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
-  --> $DIR/redundant.rs:10:27
-   |
-LL |     fn inherent(&self) -> impl Sized + use<'_> {}
-   |                           ^^^^^^^^^^^^^-------
-   |                                        |
-   |                                        help: remove the `use<...>` syntax
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
deleted file mode 100644
index 27f8ff92d3e65..0000000000000
--- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/redundant.rs:16:35
-   |
-LL |     fn in_trait() -> impl Sized + use<'a, Self>;
-   |                                   ^^^^^^^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/redundant.rs:21:35
-   |
-LL |     fn in_trait() -> impl Sized + use<'a> {}
-   |                                   ^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs
index 4a08ffb61be03..e19d935f5b0d4 100644
--- a/tests/ui/impl-trait/precise-capturing/redundant.rs
+++ b/tests/ui/impl-trait/precise-capturing/redundant.rs
@@ -1,25 +1,24 @@
 //@ compile-flags: -Zunstable-options --edition=2024
-//@ revisions: normal rpitit
-//@[normal] check-pass
+//@ check-pass
+
+#![feature(precise_capturing_in_traits)]
 
 fn hello<'a>() -> impl Sized + use<'a> {}
-//[normal]~^ WARN all possible in-scope parameters are already captured
+//~^ WARN all possible in-scope parameters are already captured
 
 struct Inherent;
 impl Inherent {
     fn inherent(&self) -> impl Sized + use<'_> {}
-    //[normal]~^ WARN all possible in-scope parameters are already captured
+    //~^ WARN all possible in-scope parameters are already captured
 }
 
-#[cfg(rpitit)]
 trait Test<'a> {
     fn in_trait() -> impl Sized + use<'a, Self>;
-    //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
+    //~^ WARN all possible in-scope parameters are already captured
 }
-#[cfg(rpitit)]
 impl<'a> Test<'a> for () {
     fn in_trait() -> impl Sized + use<'a> {}
-    //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
+    //~^ WARN all possible in-scope parameters are already captured
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr
new file mode 100644
index 0000000000000..274d9d2375f7d
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr
@@ -0,0 +1,36 @@
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:6:19
+   |
+LL | fn hello<'a>() -> impl Sized + use<'a> {}
+   |                   ^^^^^^^^^^^^^-------
+   |                                |
+   |                                help: remove the `use<...>` syntax
+   |
+   = note: `#[warn(impl_trait_redundant_captures)]` on by default
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:11:27
+   |
+LL |     fn inherent(&self) -> impl Sized + use<'_> {}
+   |                           ^^^^^^^^^^^^^-------
+   |                                        |
+   |                                        help: remove the `use<...>` syntax
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:16:22
+   |
+LL |     fn in_trait() -> impl Sized + use<'a, Self>;
+   |                      ^^^^^^^^^^^^^-------------
+   |                                   |
+   |                                   help: remove the `use<...>` syntax
+
+warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
+  --> $DIR/redundant.rs:20:22
+   |
+LL |     fn in_trait() -> impl Sized + use<'a> {}
+   |                      ^^^^^^^^^^^^^-------
+   |                                   |
+   |                                   help: remove the `use<...>` syntax
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
index 062351afecbdf..b39c1408c0509 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs
@@ -2,13 +2,14 @@
 // trait definition, which is not allowed. Due to the default lifetime capture
 // rules of RPITITs, this is only doable if we use precise capturing.
 
+#![feature(precise_capturing_in_traits)]
+
 pub trait Foo {
     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
-    //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
 }
 
 impl Foo for () {
-    fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
+    fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {}
     //~^ ERROR return type captures more lifetimes than trait definition
 }
 
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
index ffd9646a4038b..45f755d3cc1be 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr
@@ -1,28 +1,17 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53
-   |
-LL |     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
-   |                                                     ^^^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error: return type captures more lifetimes than trait definition
-  --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40
+  --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40
    |
-LL |     fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {}
-   |            ---                         ^^^^^^^^^^^^^^^^
+LL |     fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {}
+   |            ---                         ^^^^^^^^^^^^^^^^^^^^^
    |            |
    |            this lifetime was captured
    |
 note: hidden type must only reference lifetimes captured by this impl trait
-  --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40
+  --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40
    |
 LL |     fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use<Self>;
    |                                        ^^^^^^^^^^^^^^^^^^^^^^
-   = note: hidden type inferred to be `impl Sized + 'im`
+   = note: hidden type inferred to be `impl Sized`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
new file mode 100644
index 0000000000000..b16b0522d6e11
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs
@@ -0,0 +1,14 @@
+#![feature(precise_capturing_in_traits)]
+
+struct Invariant<'a>(&'a mut &'a mut ());
+
+trait Trait {
+    fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
+}
+
+impl Trait for () {
+    fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {}
+    //~^ ERROR return type captures more lifetimes than trait definition
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
new file mode 100644
index 0000000000000..e1856b929106e
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
@@ -0,0 +1,17 @@
+error: return type captures more lifetimes than trait definition
+  --> $DIR/rpitit-impl-captures-too-much.rs:10:39
+   |
+LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {}
+   |                               --      ^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this lifetime was captured
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/rpitit-impl-captures-too-much.rs:6:39
+   |
+LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Sized`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs
index feeeb1461e827..3f887e8e47f1c 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.rs
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs
@@ -1,19 +1,34 @@
-//@ known-bug: unknown
-
 // RPITITs don't have variances in their GATs, so they always relate invariantly
 // and act as if they capture all their args.
 // To fix this soundly, we need to make sure that all the trait header args
 // remain captured, since they affect trait selection.
 
-trait Foo<'a> {
-    fn hello() -> impl PartialEq + use<Self>;
+#![feature(precise_capturing_in_traits)]
+
+fn eq_types<T>(_: T, _: T) {}
+
+trait TraitLt<'a: 'a> {
+    fn hello() -> impl Sized + use<Self>;
+    //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+}
+fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () {
+    eq_types(
+        //~^ ERROR lifetime may not live long enough
+        //~| ERROR lifetime may not live long enough
+        <T as TraitLt<'a>>::hello(),
+        <T as TraitLt<'b>>::hello(),
+    );
 }
 
-fn test<'a, 'b, T: for<'r> Foo<'r>>() {
-    PartialEq::eq(
-        &<T as Foo<'a>>::hello(),
-        &<T as Foo<'b>>::hello(),
+trait MethodLt {
+    fn hello<'a: 'a>() -> impl Sized + use<Self>;
+}
+fn method_lt<'a, 'b, T: MethodLt> () {
+    eq_types(
+        T::hello::<'a>(),
+        T::hello::<'b>(),
     );
+    // Good!
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
index c162875f327cc..8c219bb04a278 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
@@ -1,47 +1,40 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/rpitit.rs:9:36
-   |
-LL |     fn hello() -> impl PartialEq + use<Self>;
-   |                                    ^^^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
-  --> $DIR/rpitit.rs:9:19
+  --> $DIR/rpitit.rs:11:19
    |
-LL | trait Foo<'a> {
-   |           -- this lifetime parameter is captured
-LL |     fn hello() -> impl PartialEq + use<Self>;
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
+LL | trait TraitLt<'a: 'a> {
+   |               -- this lifetime parameter is captured
+LL |     fn hello() -> impl Sized + use<Self>;
+   |                   ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
 
 error: lifetime may not live long enough
-  --> $DIR/rpitit.rs:13:5
+  --> $DIR/rpitit.rs:15:5
    |
-LL |   fn test<'a, 'b, T: for<'r> Foo<'r>>() {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL | /     PartialEq::eq(
-LL | |         &<T as Foo<'a>>::hello(),
-LL | |         &<T as Foo<'b>>::hello(),
+LL |   fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () {
+   |               --  -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+LL | /     eq_types(
+LL | |
+LL | |
+LL | |         <T as TraitLt<'a>>::hello(),
+LL | |         <T as TraitLt<'b>>::hello(),
 LL | |     );
    | |_____^ argument requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
 
 error: lifetime may not live long enough
-  --> $DIR/rpitit.rs:13:5
+  --> $DIR/rpitit.rs:15:5
    |
-LL |   fn test<'a, 'b, T: for<'r> Foo<'r>>() {
-   |           --  -- lifetime `'b` defined here
-   |           |
-   |           lifetime `'a` defined here
-LL | /     PartialEq::eq(
-LL | |         &<T as Foo<'a>>::hello(),
-LL | |         &<T as Foo<'b>>::hello(),
+LL |   fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () {
+   |               --  -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+LL | /     eq_types(
+LL | |
+LL | |
+LL | |         <T as TraitLt<'a>>::hello(),
+LL | |         <T as TraitLt<'b>>::hello(),
 LL | |     );
    | |_____^ argument requires that `'b` must outlive `'a`
    |
@@ -49,5 +42,5 @@ LL | |     );
 
 help: `'a` and `'b` must be the same: replace one with the other
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs
index a61a7f06edc1d..15985da50b55e 100644
--- a/tests/ui/impl-trait/precise-capturing/self-capture.rs
+++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs
@@ -1,6 +1,9 @@
+//@ check-pass
+
+#![feature(precise_capturing_in_traits)]
+
 trait Foo {
     fn bar<'a>() -> impl Sized + use<Self>;
-    //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr
deleted file mode 100644
index 45ebc429d88a7..0000000000000
--- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
-  --> $DIR/self-capture.rs:2:34
-   |
-LL |     fn bar<'a>() -> impl Sized + use<Self>;
-   |                                  ^^^^^^^^^
-   |
-   = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
-   = note: see issue #130044 <https://github.com/rust-lang/rust/issues/130044> for more information
-   = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-

From 36076ecdc726c4e1104e70df2d142f39501a4f48 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 29 Sep 2024 13:49:32 -0400
Subject: [PATCH 3/4] Clarify implicit captures for RPITIT

---
 compiler/rustc_hir_analysis/messages.ftl      |  3 +++
 .../rustc_hir_analysis/src/check/check.rs     | 25 ++++++++++++-------
 .../src/errors/precise_captures.rs            |  9 +++++++
 .../precise-capturing/rpitit.stderr           |  4 +--
 4 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index c73826c489f96..a80dc87c62242 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -259,6 +259,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
 hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
     .label = type parameter declared here
 
+hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+    .param_label = all lifetime parameters originating from a trait are captured implicitly
+
 hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
     .label = move the lifetime before this parameter
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index eb62ff86c7179..d0063b449f894 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -589,15 +589,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
                                 param_span: tcx.def_span(def_id),
                             });
                         } else {
-                            // If the `use_span` is actually just the param itself, then we must
-                            // have not duplicated the lifetime but captured the original.
-                            // The "effective" `use_span` will be the span of the opaque itself,
-                            // and the param span will be the def span of the param.
-                            tcx.dcx().emit_err(errors::LifetimeNotCaptured {
-                                opaque_span,
-                                use_span: opaque_span,
-                                param_span: use_span,
-                            });
+                            if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait {
+                                tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured {
+                                    opaque_span,
+                                    param_span: tcx.def_span(param.def_id),
+                                });
+                            } else {
+                                // If the `use_span` is actually just the param itself, then we must
+                                // have not duplicated the lifetime but captured the original.
+                                // The "effective" `use_span` will be the span of the opaque itself,
+                                // and the param span will be the def span of the param.
+                                tcx.dcx().emit_err(errors::LifetimeNotCaptured {
+                                    opaque_span,
+                                    use_span: opaque_span,
+                                    param_span: use_span,
+                                });
+                            }
                         }
                         continue;
                     }
diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
index b6cffb90805b3..8a83866b7fa46 100644
--- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
+++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
@@ -34,6 +34,15 @@ pub(crate) struct LifetimeNotCaptured {
     pub opaque_span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_lifetime_implicitly_captured)]
+pub(crate) struct LifetimeImplicitlyCaptured {
+    #[primary_span]
+    pub opaque_span: Span,
+    #[label(hir_analysis_param_label)]
+    pub param_span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_bad_precise_capture)]
 pub(crate) struct BadPreciseCapture {
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
index 8c219bb04a278..498eae54a1c68 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr
@@ -2,9 +2,9 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use
   --> $DIR/rpitit.rs:11:19
    |
 LL | trait TraitLt<'a: 'a> {
-   |               -- this lifetime parameter is captured
+   |               -- all lifetime parameters originating from a trait are captured implicitly
 LL |     fn hello() -> impl Sized + use<Self>;
-   |                   ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
+   |                   ^^^^^^^^^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
   --> $DIR/rpitit.rs:15:5

From 322c4bdac595e7689dcf08b847d0bd4d82a4bad9 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 29 Sep 2024 13:49:53 -0400
Subject: [PATCH 4/4] Don't fire refinement lint if there are errors

---
 .../rustc_hir_analysis/src/check/compare_impl_item/refine.rs  | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 80334c6efe7d6..2d6b9813271e2 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -64,6 +64,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
         return;
     };
 
+    if hidden_tys.items().any(|(_, &ty)| ty.skip_binder().references_error()) {
+        return;
+    }
+
     let mut collector = ImplTraitInTraitCollector { tcx, types: FxIndexSet::default() };
     trait_m_sig.visit_with(&mut collector);