Skip to content

Commit

Permalink
Check xform_ret_ty for WF in the new solver to improve method winnowing
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Nov 27, 2024
1 parent f2abf82 commit 4120fdb
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
22 changes: 22 additions & 0 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
47 changes: 47 additions & 0 deletions tests/ui/traits/next-solver/non-wf-ret.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 4120fdb

Please # to comment.