Skip to content

Commit f6e2337

Browse files
Auto merge of #142647 - compiler-errors:less-work-in-coherence, r=<try>
[perf] Compute hard errors without diagnostics in impl_intersection_has_impossible_obligation
2 parents f3db639 + 15a8f83 commit f6e2337

File tree

3 files changed

+28
-24
lines changed

3 files changed

+28
-24
lines changed

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ pub enum ScrubbedTraitError<'tcx> {
1919
TrueError,
2020
/// An ambiguity. This goal may hold if further inference is done.
2121
Ambiguity,
22-
/// An old-solver-style cycle error, which will fatal.
22+
/// An old-solver-style cycle error, which will fatal. This is not
23+
/// returned by the new solver.
2324
Cycle(PredicateObligations<'tcx>),
2425
}
2526

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -356,29 +356,38 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
356356
return IntersectionHasImpossibleObligations::Yes;
357357
}
358358

359-
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
359+
let ocx = ObligationCtxt::new(infcx);
360360
ocx.register_obligations(obligations.iter().cloned());
361+
let hard_errors = ocx.select_where_possible();
362+
if !hard_errors.is_empty() {
363+
assert!(
364+
hard_errors.iter().all(|e| e.is_true_error()),
365+
"should not have detected ambiguity during first pass"
366+
);
367+
return IntersectionHasImpossibleObligations::Yes;
368+
}
369+
370+
// Make a new `ObligationCtxt` and re-prove the ambiguities with a richer
371+
// `FulfillmentError`. This is so that we can detect overflowing obligations
372+
// without needing to run the `BestBestObligation` visitor on true errors.
373+
let ambiguities = ocx.into_pending_obligations();
374+
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
375+
ocx.register_obligations(ambiguities);
361376
let errors_and_ambiguities = ocx.select_all_or_error();
362377
// We only care about the obligations that are *definitely* true errors.
363378
// Ambiguities do not prove the disjointness of two impls.
364379
let (errors, ambiguities): (Vec<_>, Vec<_>) =
365380
errors_and_ambiguities.into_iter().partition(|error| error.is_true_error());
366-
367-
if errors.is_empty() {
368-
IntersectionHasImpossibleObligations::No {
369-
overflowing_predicates: ambiguities
370-
.into_iter()
371-
.filter(|error| {
372-
matches!(
373-
error.code,
374-
FulfillmentErrorCode::Ambiguity { overflow: Some(true) }
375-
)
376-
})
377-
.map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
378-
.collect(),
379-
}
380-
} else {
381-
IntersectionHasImpossibleObligations::Yes
381+
assert!(errors.is_empty(), "should not have ambiguities during second pass");
382+
383+
IntersectionHasImpossibleObligations::No {
384+
overflowing_predicates: ambiguities
385+
.into_iter()
386+
.filter(|error| {
387+
matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) })
388+
})
389+
.map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
390+
.collect(),
382391
}
383392
} else {
384393
for obligation in obligations {

tests/crashes/139905.rs

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)