about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-11-27 02:44:24 +0000
committerMichael Goulet <michael@errs.io>2024-11-27 20:46:08 +0000
commit4120fdbeab225daddec7436755074e688c8087c3 (patch)
treee0523a96873608b887c099b5564a16f7e9e0eca6
parentf2abf827c128120ed7a874d02973947968c158b8 (diff)
downloadrust-4120fdbeab225daddec7436755074e688c8087c3.tar.gz
rust-4120fdbeab225daddec7436755074e688c8087c3.zip
Check xform_ret_ty for WF in the new solver to improve method winnowing
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs22
-rw-r--r--tests/ui/traits/next-solver/non-wf-ret.rs47
2 files changed, 69 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 640729576fc..5aaad3636a2 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1642,6 +1642,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 }
             }
 
+            // FIXME(-Znext-solver): See the linked issue below.
+            // <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>
+            //
+            // In the new solver, check the well-formedness of the return type.
+            // This emulates, in a way, the predicates that fall out of
+            // normalizing the return type in the old solver.
+            //
+            // We alternatively could check the predicates of the method itself hold,
+            // but we intentionally do not do this in the old solver b/c of cycles,
+            // and doing it in the new solver would be stronger. This should be fixed
+            // in the future, since it likely leads to much better method winnowing.
+            if let Some(xform_ret_ty) = xform_ret_ty
+                && self.infcx.next_trait_solver()
+            {
+                ocx.register_obligation(traits::Obligation::new(
+                    self.tcx,
+                    cause.clone(),
+                    self.param_env,
+                    ty::ClauseKind::WellFormed(xform_ret_ty.into()),
+                ));
+            }
+
             // Evaluate those obligations to see if they might possibly hold.
             for error in ocx.select_where_possible() {
                 result = ProbeResult::NoMatch;
diff --git a/tests/ui/traits/next-solver/non-wf-ret.rs b/tests/ui/traits/next-solver/non-wf-ret.rs
new file mode 100644
index 00000000000..c54d61c895d
--- /dev/null
+++ b/tests/ui/traits/next-solver/non-wf-ret.rs
@@ -0,0 +1,47 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+use std::ops::Deref;
+
+pub struct List<T> {
+    skel: [T],
+}
+
+impl<'a, T: Copy> IntoIterator for &'a List<T> {
+    type Item = T;
+    type IntoIter = std::iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        todo!()
+    }
+}
+
+impl<T> Deref for List<T> {
+    type Target = [T];
+
+    fn deref(&self) -> &[T] {
+        todo!()
+    }
+}
+
+impl<T> List<T> {
+    fn iter(&self) -> <&Self as IntoIterator>::IntoIter
+    where
+        T: Copy,
+    {
+        todo!()
+    }
+}
+
+fn test<Q>(t: &List<Q>) {
+    // Checking that `<&List<Q> as IntoIterator>::IntoIter` is WF
+    // will disqualify the inherent method, since normalizing it
+    // requires `Q: Copy` which does not hold. and allow us to fall
+    // through to the deref'd `<[Q]>::iter` method which works.
+    //
+    // In the old solver, the same behavior is achieved by just
+    // eagerly normalizing the return type.
+    t.iter();
+}
+
+fn main() {}