From 398fd901d5f8afa982eeb0f9318d9d0e4e791f44 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Nov 2024 21:27:37 +0000 Subject: [PATCH] Assert that obligations are empty before deeply normalizing --- .../src/obligation_forest/mod.rs | 4 ++++ compiler/rustc_hir_analysis/src/check/wfcheck.rs | 3 +-- compiler/rustc_infer/src/traits/engine.rs | 2 ++ compiler/rustc_trait_selection/src/solve/fulfill.rs | 4 ++++ .../rustc_trait_selection/src/traits/fulfill.rs | 4 ++++ .../rustc_trait_selection/src/traits/normalize.rs | 9 +++++++++ .../traits/query/type_op/implied_outlives_bounds.rs | 3 +++ .../ui/higher-ranked/structually-relate-aliases.rs | 1 - .../higher-ranked/structually-relate-aliases.stderr | 13 +------------ .../in-trait/alias-bounds-when-not-wf.stderr | 4 ++-- .../traits/next-solver/issue-118950-root-region.rs | 2 +- .../next-solver/issue-118950-root-region.stderr | 13 ++++++------- 12 files changed, 37 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 34a2464972a6e..78d69a66edc8b 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -415,6 +415,10 @@ impl ObligationForest { .collect() } + pub fn has_pending_obligations(&self) -> bool { + self.nodes.iter().any(|node| node.state.get() == NodeState::Pending) + } + fn insert_into_error_cache(&mut self, index: usize) { let node = &self.nodes[index]; self.error_cache diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8fa797db24661..6804540393292 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -116,13 +116,12 @@ where } f(&mut wfcx)?; - let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; - let errors = wfcx.select_all_or_error(); if !errors.is_empty() { return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; debug!(?assumed_wf_types); let infcx_compat = infcx.fork(); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index ba1516655b0bc..51282b900ed14 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -84,6 +84,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { self.collect_remaining_errors(infcx) } + fn has_pending_obligations(&self) -> bool; + fn pending_obligations(&self) -> PredicateObligations<'tcx>; /// Among all pending obligations, collect those are stalled on a inference variable which has diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0f90c45d0320c..2b2623a050ec9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -199,6 +199,10 @@ where errors } + fn has_pending_obligations(&self) -> bool { + !self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 03e483f555d8e..7529ee128f5e4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -213,6 +213,10 @@ where } } + fn has_pending_obligations(&self) -> bool { + self.predicates.has_pending_obligations() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 2891df3ed2dd8..ad62b456ad461 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -7,6 +7,7 @@ use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; use rustc_macros::extension; +use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, @@ -63,6 +64,14 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { + if fulfill_cx.has_pending_obligations() { + let pending_obligations = fulfill_cx.pending_obligations(); + span_bug!( + pending_obligations[0].cause.span, + "deeply_normalize should not be called with pending obligations: \ + {pending_obligations:#?}" + ); + } let value = self .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 224a727147276..fe47e837dfb53 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -60,6 +60,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( ty: Ty<'tcx>, ) -> Result>, NoSolution> { let normalize_op = |ty| -> Result<_, NoSolution> { + // We must normalize the type so we can compute the right outlives components. + // for example, if we have some constrained param type like `T: Trait`, + // and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`. let ty = ocx .deeply_normalize(&ObligationCause::dummy(), param_env, ty) .map_err(|_| NoSolution)?; diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 73c2cd23d86e3..1ed3767643a00 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -12,6 +12,5 @@ impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} //~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied -//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index e9d91e45e217b..cf3e4cc85b912 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -10,17 +10,6 @@ help: consider restricting type parameter `T` LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} | ++++++++++++++++++++ -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:17 - | -LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 79581066a3a32..1cfc2a6d94495 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -8,10 +8,10 @@ LL | #![feature(lazy_type_alias)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `usize: Foo` is not satisfied - --> $DIR/alias-bounds-when-not-wf.rs:16:13 + --> $DIR/alias-bounds-when-not-wf.rs:16:15 | LL | fn hello(_: W>) {} - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize` + | ^^^^^^^^ the trait `Foo` is not implemented for `usize` | help: this trait has no implementations, consider adding one --> $DIR/alias-bounds-when-not-wf.rs:6:1 diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index e1bd234a275a6..8fe53d6773b95 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -18,6 +18,6 @@ impl Overlap for T {} impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} //~^ ERROR cannot find type `Missing` in this scope -//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied +//~| ERROR the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index f6545c6ebf9de..09162970d33da 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,17 +26,16 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } -error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied - --> $DIR/issue-118950-root-region.rs:19:17 +error[E0277]: the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied + --> $DIR/issue-118950-root-region.rs:19:47 | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T` + | ^ the trait `Overlap fn(Assoc<'a, T>)>` is not implemented for `T` | -help: this trait has no implementations, consider adding one - --> $DIR/issue-118950-root-region.rs:8:1 +help: consider further restricting type parameter `T` | -LL | trait ToUnit<'a> { - | ^^^^^^^^^^^^^^^^ +LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap, T: Overlap fn(Assoc<'a, T>)> {} + | ++++++++++++++++++++++++++++++++++++++ error: aborting due to 3 previous errors; 1 warning emitted