diff options
| author | Michael Goulet <michael@errs.io> | 2025-06-26 20:15:20 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-26 20:15:20 -0400 |
| commit | 25e239c193b3e22d0dc5e8e3eaebd66ed9b7374b (patch) | |
| tree | f64aa341aafbc40ce3aa5678865cf8acaa6db015 /compiler/rustc_trait_selection/src/traits | |
| parent | 48d311898b2f4fd2437df206e910c0d63d20061f (diff) | |
| parent | 83044357930a7c55f8d429bd4cd7dcb7426d4b01 (diff) | |
| download | rust-25e239c193b3e22d0dc5e8e3eaebd66ed9b7374b.tar.gz rust-25e239c193b3e22d0dc5e8e3eaebd66ed9b7374b.zip | |
Rollup merge of #142647 - compiler-errors:less-work-in-coherence, r=lcnr
[perf] Compute hard errors without diagnostics in impl_intersection_has_impossible_obligation First compute hard errors without diagnostics, then ambiguities with diagnostics since we need to know if any of them overflowed.
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/coherence.rs | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 81893cdcc7e..ce5a4edeaaa 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -356,29 +356,38 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( return IntersectionHasImpossibleObligations::Yes; } - let ocx = ObligationCtxt::new_with_diagnostics(infcx); + let ocx = ObligationCtxt::new(infcx); ocx.register_obligations(obligations.iter().cloned()); + let hard_errors = ocx.select_where_possible(); + if !hard_errors.is_empty() { + assert!( + hard_errors.iter().all(|e| e.is_true_error()), + "should not have detected ambiguity during first pass" + ); + return IntersectionHasImpossibleObligations::Yes; + } + + // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer + // `FulfillmentError`. This is so that we can detect overflowing obligations + // without needing to run the `BestObligation` visitor on true errors. + let ambiguities = ocx.into_pending_obligations(); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + ocx.register_obligations(ambiguities); let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. // Ambiguities do not prove the disjointness of two impls. let (errors, ambiguities): (Vec<_>, Vec<_>) = errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); - - if errors.is_empty() { - IntersectionHasImpossibleObligations::No { - overflowing_predicates: ambiguities - .into_iter() - .filter(|error| { - matches!( - error.code, - FulfillmentErrorCode::Ambiguity { overflow: Some(true) } - ) - }) - .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) - .collect(), - } - } else { - IntersectionHasImpossibleObligations::Yes + assert!(errors.is_empty(), "should not have ambiguities during second pass"); + + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) + }) + .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate)) + .collect(), } } else { for obligation in obligations { |
