diff options
| author | Michael Goulet <michael@errs.io> | 2024-11-27 02:44:24 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-11-27 20:46:08 +0000 |
| commit | 4120fdbeab225daddec7436755074e688c8087c3 (patch) | |
| tree | e0523a96873608b887c099b5564a16f7e9e0eca6 | |
| parent | f2abf827c128120ed7a874d02973947968c158b8 (diff) | |
| download | rust-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.rs | 22 | ||||
| -rw-r--r-- | tests/ui/traits/next-solver/non-wf-ret.rs | 47 |
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() {} |
