about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2024-02-29 05:25:28 -0500
committerGitHub <noreply@github.com>2024-02-29 05:25:28 -0500
commit23351388d094e6f0280ca2bc9a63f98ce50ca2e7 (patch)
tree379d80710ff2319b5a5975fd3ac33c2fcc7dd9e6
parent69716291c365cfa59f3ca3fcbd4c81fa837dfe80 (diff)
parent75e15f7cf4e55ed9572781930ee8babcaa256a47 (diff)
downloadrust-23351388d094e6f0280ca2bc9a63f98ce50ca2e7.tar.gz
rust-23351388d094e6f0280ca2bc9a63f98ce50ca2e7.zip
Rollup merge of #121745 - compiler-errors:refining-impl-trait-deeply-norm, r=lcnr
Deeply normalize obligations in `refining_impl_trait`

We somewhat awkwardly use semantic comparison when checking the `refining_impl_trait` lint. This relies on us being able to normalize bounds eagerly to avoid cases where an unnormalized alias is not considered equal to a normalized alias. Since `normalize` in the new solver is a noop, let's use `deeply_normalize` instead.

r? lcnr

cc ``@tmandry,`` this should fix your bug lol
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs9
-rw-r--r--tests/ui/impl-trait/in-trait/refine-normalize.rs20
3 files changed, 38 insertions, 5 deletions
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 b5e69b8e376..29dc434ab45 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
@@ -136,11 +136,15 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     // 1. Project the RPITIT projections from the trait to the opaques on the impl,
     //    which means that they don't need to be mapped manually.
     //
-    // 2. Project any other projections that show up in the bound. That makes sure that
-    //    we don't consider `tests/ui/async-await/in-trait/async-associated-types.rs`
-    //    to be refining.
-    let (trait_bounds, impl_bounds) =
-        ocx.normalize(&ObligationCause::dummy(), param_env, (trait_bounds, impl_bounds));
+    // 2. Deeply normalize any other projections that show up in the bound. That makes sure
+    //    that we don't consider `tests/ui/async-await/in-trait/async-associated-types.rs`
+    //    or `tests/ui/impl-trait/in-trait/refine-normalize.rs` to be refining.
+    let Ok((trait_bounds, impl_bounds)) =
+        ocx.deeply_normalize(&ObligationCause::dummy(), param_env, (trait_bounds, impl_bounds))
+    else {
+        tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)");
+        return;
+    };
 
     // Since we've normalized things, we need to resolve regions, since we'll
     // possibly have introduced region vars during projection. We don't expect
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 1aaadf6cf04..e789e9c2b6e 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -107,6 +107,15 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         self.register_infer_ok_obligations(infer_ok)
     }
 
+    pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+        self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
+    }
+
     /// Makes `expected <: actual`.
     pub fn eq_exp<T>(
         &self,
diff --git a/tests/ui/impl-trait/in-trait/refine-normalize.rs b/tests/ui/impl-trait/in-trait/refine-normalize.rs
new file mode 100644
index 00000000000..95f2cda6a74
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/refine-normalize.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+//@ edition: 2021
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![deny(refining_impl_trait)]
+
+pub trait Foo {
+    type Item;
+
+    fn hello() -> impl Iterator<Item = Self::Item>;
+}
+
+impl Foo for () {
+    type Item = ();
+
+    fn hello() -> impl Iterator<Item = ()> { [()].into_iter() }
+}
+
+fn main() {}