From b6b5a65ae6714f39a2d2dcf5909fee9f64dd4dcd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Aug 2023 22:21:55 +0000 Subject: [PATCH] Select obligations before processing wf obligation in compare_method_predicate_entailment --- .../src/check/compare_impl_item.rs | 11 +++++++- ...ounds-entailment-wf-vars-issue-114783-1.rs | 26 +++++++++++++++++++ ...ounds-entailment-wf-vars-issue-114783-2.rs | 26 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 044fb405e32..ad02ca252c4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -308,6 +308,15 @@ fn compare_method_predicate_entailment<'tcx>( } if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() { + // Select obligations to make progress on inference before processing + // the wf obligation below. + // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed. + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + return Err(reported); + } + // See #108544. Annoying, we can end up in cases where, because of winnowing, // we pick param env candidates over a more general impl, leading to more // stricter lifetime requirements than we would otherwise need. This can @@ -378,7 +387,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), + infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { diff --git a/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs new file mode 100644 index 00000000000..9b793642d07 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs @@ -0,0 +1,26 @@ +// check-pass + +pub trait Foo { + type Error: Error; + + fn foo(&self, stream: &::Span); +} + +pub struct Wrapper(Inner); + +impl Foo for Wrapper +where + Inner: Foo, +{ + type Error = E; + + fn foo(&self, stream: &::Span) { + todo!() + } +} + +pub trait Error { + type Span; +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs new file mode 100644 index 00000000000..86b10a56c9d --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs @@ -0,0 +1,26 @@ +// check-pass + +trait AsBufferView { + type Device; +} + +trait Error { + type Span; +} + +trait Foo { + type Error: Error; + fn foo(&self) -> &::Span; +} + +impl Foo for VBuf0 +where + VBuf0: AsBufferView, +{ + type Error = D; + fn foo(&self) -> &::Span { + todo!() + } +} + +fn main() {}