about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-10-04 00:02:26 +0000
committerbors <bors@rust-lang.org>2025-10-04 00:02:26 +0000
commit7950f244e7ef55b61a83d12f4662be643cd182d6 (patch)
tree6f741b4059ce1061d04ffa47c43658535c62b6f3
parent595b9a498bc55fcd30111e430d8e4290ed833b4c (diff)
parente3f104608c0ad26e80b1ebedef2ab8a748189e52 (diff)
downloadrust-7950f244e7ef55b61a83d12f4662be643cd182d6.tar.gz
rust-7950f244e7ef55b61a83d12f4662be643cd182d6.zip
Auto merge of #147299 - compiler-errors:hr-norm, r=jackh726
Don't normalize higher-ranked assumptions if they're not used

See the comment in the code.

Normalizing these assumptions may cause us to register things like new placeholder outlives obligations that cause higher-ranked lifetime errors, and this is problematic if we're not even using these assumptions in borrowck.

Fixes rust-lang/rust#147244
Fixes rust-lang/rust#147285
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs31
-rw-r--r--tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs38
-rw-r--r--tests/ui/async-await/higher-ranked-normalize-assumptions.rs51
3 files changed, 107 insertions, 13 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 7ad65a1df8e..708a53f6c65 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -423,19 +423,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 constituents.types,
             );
 
-            // FIXME(coroutine_clone): We could uplift this into `collect_predicates_for_types`
-            // and do this for `Copy`/`Clone` too, but that's feature-gated so it doesn't really
-            // matter yet.
-            for assumption in constituents.assumptions {
-                let assumption = normalize_with_depth_to(
-                    self,
-                    obligation.param_env,
-                    cause.clone(),
-                    obligation.recursion_depth + 1,
-                    assumption,
-                    &mut obligations,
-                );
-                self.infcx.register_region_assumption(assumption);
+            // Only normalize these goals if `-Zhigher-ranked-assumptions` is enabled, since
+            // we don't want to cause ourselves to do extra work if we're not even able to
+            // take advantage of these assumption clauses.
+            if self.tcx().sess.opts.unstable_opts.higher_ranked_assumptions {
+                // FIXME(coroutine_clone): We could uplift this into `collect_predicates_for_types`
+                // and do this for `Copy`/`Clone` too, but that's feature-gated so it doesn't really
+                // matter yet.
+                for assumption in constituents.assumptions {
+                    let assumption = normalize_with_depth_to(
+                        self,
+                        obligation.param_env,
+                        cause.clone(),
+                        obligation.recursion_depth + 1,
+                        assumption,
+                        &mut obligations,
+                    );
+                    self.infcx.register_region_assumption(assumption);
+                }
             }
 
             Ok(obligations)
diff --git a/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs b/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs
new file mode 100644
index 00000000000..410d4e503b7
--- /dev/null
+++ b/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs
@@ -0,0 +1,38 @@
+//@ revisions: stock hr
+//@[hr] compile-flags: -Zhigher-ranked-assumptions
+//@ edition: 2024
+//@ check-pass
+
+// Test that we don't normalize the higher-ranked assumptions of an auto trait goal
+// unless we have `-Zhigher-ranked-assumptions`, since obligations that result from
+// this normalization may lead to higher-ranked lifetime errors when the flag is not
+// enabled.
+
+// Regression test for <https://github.com/rust-lang/rust/issues/147244>.
+
+pub fn a() -> impl Future + Send {
+    async {
+        let queries = core::iter::empty().map(Thing::f);
+        b(queries).await;
+    }
+}
+
+async fn b(queries: impl IntoIterator) {
+    c(queries).await;
+}
+
+fn c<'a, I>(_queries: I) -> impl Future
+where
+    I: IntoIterator,
+    I::IntoIter: 'a,
+{
+    async {}
+}
+
+pub struct Thing<'a>(pub &'a ());
+
+impl Thing<'_> {
+    fn f(_: &Self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/higher-ranked-normalize-assumptions.rs b/tests/ui/async-await/higher-ranked-normalize-assumptions.rs
new file mode 100644
index 00000000000..ec9cf3a1522
--- /dev/null
+++ b/tests/ui/async-await/higher-ranked-normalize-assumptions.rs
@@ -0,0 +1,51 @@
+//@ revisions: stock hr
+//@[hr] compile-flags: -Zhigher-ranked-assumptions
+//@ edition: 2024
+//@ check-pass
+
+// Test that we don't normalize the higher-ranked assumptions of an auto trait goal
+// unless we have `-Zhigher-ranked-assumptions`, since obligations that result from
+// this normalization may lead to higher-ranked lifetime errors when the flag is not
+// enabled.
+
+// Regression test for <https://github.com/rust-lang/rust/issues/147285>.
+
+pub trait Service {
+    type Response;
+}
+
+impl<T, R> Service for T
+where
+    T: FnMut() -> R,
+    R: 'static,
+{
+    type Response = R;
+}
+
+async fn serve<C>(_: C)
+where
+    C: Service,
+    C::Response: 'static,
+{
+    connect::<C>().await;
+}
+
+async fn connect<C>()
+where
+    C: Service,
+    C::Response: 'static,
+{
+}
+
+fn repro() -> impl Send {
+    async {
+        let server = || do_something();
+        serve(server).await;
+    }
+}
+
+fn do_something() -> Box<dyn std::error::Error> {
+    unimplemented!()
+}
+
+fn main() {}