Skip to content

Commit a569706

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

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

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

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

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

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

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

0 commit comments

Comments
 (0)