Reduce the scope of allow(rustc::potential_query_instability) in rustc_trait_selection

Make InferCtxtExt use a FxIndexMap

This should be faster, because the map is only being used to iterate,
which is supposed to be faster with the IndexMap

Make the user_computed_preds use an IndexMap

It is being used mostly for iteration, so the change shouldn't result in
a perf hit

Make the RegionDeps fields use an IndexMap

This change could be a perf hit. Both `larger` and `smaller` are used
for iteration, but they are also used for insertions.

Make types_without_default_bounds use an IndexMap

It uses extend, but it also iterates and removes items. Not sure if
this will be a perf hit.

Make InferTtxt.reported_trait_errors use an IndexMap

This change brought a lot of other changes. The map seems to have been
mostly used for iteration, so the performance shouldn't suffer.

Add FIXME to change ProvisionalEvaluationCache.map to use an IndexMap

Right now this results in a perf hit. IndexMap doesn't have
the `drain_filter` API, so in `on_completion` we now need to iterate two
times over the map.
This commit is contained in:
CastilloDel 2022-10-28 23:32:41 +02:00
parent ddfe1e87f7
commit 755ca4b9aa
10 changed files with 37 additions and 30 deletions

View File

@ -1,7 +1,7 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@ -256,7 +256,7 @@ fn compare_predicate_entailment<'tcx>(
// Compute placeholder form of impl and trait method tys.
let tcx = infcx.tcx;
let mut wf_tys = FxHashSet::default();
let mut wf_tys = FxIndexSet::default();
let impl_sig = infcx.replace_bound_vars_with_fresh_vars(
impl_m_span,
@ -479,7 +479,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig);
let trait_return_ty = trait_sig.output();
let wf_tys = FxHashSet::from_iter(
let wf_tys = FxIndexSet::from_iter(
unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()),
);

View File

@ -1,7 +1,7 @@
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use hir::def::DefKind;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
@ -412,7 +412,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
.iter()
.copied()
.collect::<Vec<_>>(),
&FxHashSet::default(),
&FxIndexSet::default(),
gat_def_id.def_id,
gat_generics,
)
@ -462,10 +462,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
.into_iter()
.filter(|clause| match clause.kind().skip_binder() {
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
!region_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
!region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
}
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
!ty_known_to_outlive(tcx, gat_hir, param_env, &FxHashSet::default(), a, b)
!ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
}
_ => bug!("Unexpected PredicateKind"),
})
@ -547,7 +547,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
param_env: ty::ParamEnv<'tcx>,
item_hir: hir::HirId,
to_check: T,
wf_tys: &FxHashSet<Ty<'tcx>>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
gat_def_id: LocalDefId,
gat_generics: &'tcx ty::Generics,
) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
@ -654,7 +654,7 @@ fn ty_known_to_outlive<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
) -> bool {
@ -671,7 +671,7 @@ fn region_known_to_outlive<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
region_a: ty::Region<'tcx>,
region_b: ty::Region<'tcx>,
) -> bool {
@ -695,7 +695,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because

View File

@ -10,6 +10,7 @@
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::Rollback;
@ -294,7 +295,7 @@ pub struct InferCtxt<'tcx> {
/// the set of predicates on which errors have been reported, to
/// avoid reporting the same error twice.
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
pub reported_trait_errors: RefCell<FxIndexMap<Span, Vec<ty::Predicate<'tcx>>>>,
pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,

View File

@ -10,7 +10,6 @@
//!
//! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)]
#![feature(control_flow_enum)]

View File

@ -12,7 +12,7 @@
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{PolyTraitRef, Region, RegionVid};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use std::collections::hash_map::Entry;
use std::collections::VecDeque;
@ -27,8 +27,8 @@ pub enum RegionTarget<'tcx> {
#[derive(Default, Debug, Clone)]
pub struct RegionDeps<'tcx> {
larger: FxHashSet<RegionTarget<'tcx>>,
smaller: FxHashSet<RegionTarget<'tcx>>,
larger: FxIndexSet<RegionTarget<'tcx>>,
smaller: FxIndexSet<RegionTarget<'tcx>>,
}
pub enum AutoTraitResult<A> {
@ -266,7 +266,7 @@ fn evaluate_predicates(
}));
let computed_preds = param_env.caller_bounds().iter();
let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect();
let mut user_computed_preds: FxIndexSet<_> = user_env.caller_bounds().iter().collect();
let mut new_env = param_env;
let dummy_cause = ObligationCause::dummy();
@ -389,7 +389,7 @@ fn evaluate_predicates(
/// not just one specific lifetime (e.g., `'static`).
fn add_user_pred(
&self,
user_computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
user_computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
new_pred: ty::Predicate<'tcx>,
) {
let mut should_add_new = true;
@ -585,7 +585,7 @@ fn evaluate_nested_obligations(
&self,
ty: Ty<'_>,
nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
computed_preds: &mut FxIndexSet<ty::Predicate<'tcx>>,
fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
select: &mut SelectionContext<'_, 'tcx>,

View File

@ -4,7 +4,7 @@
use super::TraitEngine;
use super::{ChalkFulfillmentContext, FulfillmentContext};
use crate::infer::InferCtxtExt;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::{
@ -153,10 +153,10 @@ pub fn assumed_wf_types(
param_env: ty::ParamEnv<'tcx>,
span: Span,
def_id: LocalDefId,
) -> FxHashSet<Ty<'tcx>> {
) -> FxIndexSet<Ty<'tcx>> {
let tcx = self.infcx.tcx;
let assumed_wf_types = tcx.assumed_wf_types(def_id);
let mut implied_bounds = FxHashSet::default();
let mut implied_bounds = FxIndexSet::default();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let cause = ObligationCause::misc(span, hir_id);
for ty in assumed_wf_types {

View File

@ -14,7 +14,7 @@
use crate::traits::specialize::to_pretty_impl_header;
use on_unimplemented::OnUnimplementedNote;
use on_unimplemented::TypeErrCtxtExt as _;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
MultiSpan, Style,
@ -378,7 +378,7 @@ struct ErrorDescriptor<'tcx> {
index: Option<usize>, // None if this is an old error
}
let mut error_map: FxHashMap<_, Vec<_>> = self
let mut error_map: FxIndexMap<_, Vec<_>> = self
.reported_trait_errors
.borrow()
.iter()

View File

@ -2,7 +2,7 @@
use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use crate::traits::query::NoSolution;
use crate::traits::ObligationCause;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_middle::ty::{self, ParamEnv, Ty};
@ -22,7 +22,7 @@ fn implied_bounds_tys(
&'a self,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
tys: FxHashSet<Ty<'tcx>>,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx>;
}
@ -103,7 +103,7 @@ fn implied_bounds_tys(
&'a self,
param_env: ParamEnv<'tcx>,
body_id: HirId,
tys: FxHashSet<Ty<'tcx>>,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx> {
tys.into_iter()
.map(move |ty| {

View File

@ -2,6 +2,12 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to
// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be
// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap`
// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242
#![allow(rustc::potential_query_instability)]
use self::EvaluationResult::*;
use self::SelectionCandidate::*;
@ -24,7 +30,8 @@
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;

View File

@ -16,7 +16,7 @@
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::{self, ImplSubject, TyCtxt};
@ -435,7 +435,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
// FIXME: Currently only handles ?Sized.
// Needs to support ?Move and ?DynSized when they are implemented.
let mut types_without_default_bounds = FxHashSet::default();
let mut types_without_default_bounds = FxIndexSet::default();
let sized_trait = tcx.lang_items().sized_trait();
if !substs.is_empty() {