Rollup merge of #106468 - compiler-errors:err-instability, r=lcnr

Use FxIndexSet when updating obligation causes in `adjust_fulfillment_errors_for_expr_obligation`

I have no idea how to test this reliably, but I've **manually** verified it fixes the instability in #106417 that isn't due to dtolnay/trybuild#212.

Fixes #106417
This commit is contained in:
fee1-dead 2023-01-09 23:35:31 +08:00 committed by GitHub
commit 357128ad23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,7 +9,7 @@ use crate::{
TupleArgumentsFlag, TupleArgumentsFlag,
}; };
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan}; use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
@ -1698,7 +1698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind. // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
// This is important since if we adjust one span but not the other, then // This is important since if we adjust one span but not the other, then
// we will have "duplicated" the error on the UI side. // we will have "duplicated" the error on the UI side.
let mut remap_cause = FxHashSet::default(); let mut remap_cause = FxIndexSet::default();
let mut not_adjusted = vec![]; let mut not_adjusted = vec![];
for error in errors { for error in errors {
@ -1726,6 +1726,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
// Adjust any other errors that come from other cause codes, when these
// errors are of the same predicate as one we successfully adjusted, and
// when their spans overlap (suggesting they're due to the same root cause).
//
// This is because due to normalization, we often register duplicate
// obligations with misc obligations that are basically impossible to
// line back up with a useful ExprBindingObligation.
for error in not_adjusted { for error in not_adjusted {
for (span, predicate, cause) in &remap_cause { for (span, predicate, cause) in &remap_cause {
if *predicate == error.obligation.predicate if *predicate == error.obligation.predicate