Skip to content

Commit 4120fdb

Browse files
Check xform_ret_ty for WF in the new solver to improve method winnowing
1 parent f2abf82 commit 4120fdb

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

Diff for: compiler/rustc_hir_typeck/src/method/probe.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
16421642
}
16431643
}
16441644

1645+
// FIXME(-Znext-solver): See the linked issue below.
1646+
// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/134>
1647+
//
1648+
// In the new solver, check the well-formedness of the return type.
1649+
// This emulates, in a way, the predicates that fall out of
1650+
// normalizing the return type in the old solver.
1651+
//
1652+
// We alternatively could check the predicates of the method itself hold,
1653+
// but we intentionally do not do this in the old solver b/c of cycles,
1654+
// and doing it in the new solver would be stronger. This should be fixed
1655+
// in the future, since it likely leads to much better method winnowing.
1656+
if let Some(xform_ret_ty) = xform_ret_ty
1657+
&& self.infcx.next_trait_solver()
1658+
{
1659+
ocx.register_obligation(traits::Obligation::new(
1660+
self.tcx,
1661+
cause.clone(),
1662+
self.param_env,
1663+
ty::ClauseKind::WellFormed(xform_ret_ty.into()),
1664+
));
1665+
}
1666+
16451667
// Evaluate those obligations to see if they might possibly hold.
16461668
for error in ocx.select_where_possible() {
16471669
result = ProbeResult::NoMatch;

Diff for: tests/ui/traits/next-solver/non-wf-ret.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//@ check-pass
2+
//@ compile-flags: -Znext-solver
3+
4+
use std::ops::Deref;
5+
6+
pub struct List<T> {
7+
skel: [T],
8+
}
9+
10+
impl<'a, T: Copy> IntoIterator for &'a List<T> {
11+
type Item = T;
12+
type IntoIter = std::iter::Copied<<&'a [T] as IntoIterator>::IntoIter>;
13+
14+
fn into_iter(self) -> Self::IntoIter {
15+
todo!()
16+
}
17+
}
18+
19+
impl<T> Deref for List<T> {
20+
type Target = [T];
21+
22+
fn deref(&self) -> &[T] {
23+
todo!()
24+
}
25+
}
26+
27+
impl<T> List<T> {
28+
fn iter(&self) -> <&Self as IntoIterator>::IntoIter
29+
where
30+
T: Copy,
31+
{
32+
todo!()
33+
}
34+
}
35+
36+
fn test<Q>(t: &List<Q>) {
37+
// Checking that `<&List<Q> as IntoIterator>::IntoIter` is WF
38+
// will disqualify the inherent method, since normalizing it
39+
// requires `Q: Copy` which does not hold. and allow us to fall
40+
// through to the deref'd `<[Q]>::iter` method which works.
41+
//
42+
// In the old solver, the same behavior is achieved by just
43+
// eagerly normalizing the return type.
44+
t.iter();
45+
}
46+
47+
fn main() {}

0 commit comments

Comments
 (0)