From cfb310939b9098cf5fd211c2c176eb0b2b2498fa Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 4 Jul 2023 16:22:01 +0200 Subject: [PATCH 1/2] Enable potential_query_instability lint in rustc_hir_typeck. Fix linting errors by using FxIndex(Map|Set) and Unord(Map|Set) as appropriate. --- compiler/rustc_data_structures/src/unord.rs | 21 ++- compiler/rustc_hir_typeck/src/fallback.rs | 32 ++-- .../drop_ranges/cfg_build.rs | 6 +- .../src/generator_interior/drop_ranges/mod.rs | 10 +- .../drop_ranges/record_consumed_borrow.rs | 8 +- compiler/rustc_hir_typeck/src/inherited.rs | 6 +- compiler/rustc_hir_typeck/src/lib.rs | 1 - .../rustc_hir_typeck/src/method/suggest.rs | 30 ++-- compiler/rustc_hir_typeck/src/upvar.rs | 41 +++--- compiler/rustc_hir_typeck/src/writeback.rs | 137 ++++++++++-------- compiler/rustc_middle/src/middle/region.rs | 4 +- compiler/rustc_middle/src/ty/closure.rs | 8 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/rvalue_scopes.rs | 4 +- .../rustc_middle/src/ty/typeck_results.rs | 12 +- 15 files changed, 175 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 2b21815b687d5..ec779854f361f 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -31,6 +31,7 @@ use crate::{ /// /// It's still possible to do the same thing with an `Fn` by using interior mutability, /// but the chance of doing it accidentally is reduced. +#[derive(Clone)] pub struct UnordItems>(I); impl> UnordItems { @@ -194,6 +195,11 @@ impl UnordSet { Self { inner: Default::default() } } + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self { inner: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) } + } + #[inline] pub fn len(&self) -> usize { self.inner.len() @@ -258,9 +264,9 @@ impl UnordSet { #[inline] pub fn to_sorted_stable_ord(&self) -> Vec where - V: Ord + StableOrd + Copy, + V: Ord + StableOrd + Clone, { - let mut items: Vec = self.inner.iter().copied().collect(); + let mut items: Vec = self.inner.iter().cloned().collect(); items.sort_unstable(); items } @@ -312,6 +318,12 @@ impl From> for UnordSet { } } +impl> From> for UnordSet { + fn from(value: UnordItems) -> Self { + UnordSet { inner: FxHashSet::from_iter(value.0) } + } +} + impl> HashStable for UnordSet { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { @@ -362,6 +374,11 @@ impl> From> fo } impl UnordMap { + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self { inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) } + } + #[inline] pub fn len(&self) -> usize { self.inner.len() diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index a76db6e73a1b8..5b5986a349f07 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -1,8 +1,8 @@ use crate::FnCtxt; use rustc_data_structures::{ - fx::{FxHashMap, FxHashSet}, graph::WithSuccessors, graph::{iterate::DepthFirstSearch, vec_graph::VecGraph}, + unord::{UnordBag, UnordMap, UnordSet}, }; use rustc_middle::ty::{self, Ty}; @@ -83,7 +83,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn fallback_if_possible( &self, ty: Ty<'tcx>, - diverging_fallback: &FxHashMap, Ty<'tcx>>, + diverging_fallback: &UnordMap, Ty<'tcx>>, ) { // Careful: we do NOT shallow-resolve `ty`. We know that `ty` // is an unsolved variable, and we determine its fallback @@ -193,7 +193,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn calculate_diverging_fallback( &self, unsolved_variables: &[Ty<'tcx>], - ) -> FxHashMap, Ty<'tcx>> { + ) -> UnordMap, Ty<'tcx>> { debug!("calculate_diverging_fallback({:?})", unsolved_variables); // Construct a coercion graph where an edge `A -> B` indicates @@ -210,10 +210,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // // These variables are the ones that are targets for fallback to // either `!` or `()`. - let diverging_roots: FxHashSet = self + let diverging_roots: UnordSet = self .diverging_type_vars .borrow() - .iter() + .items() .map(|&ty| self.shallow_resolve(ty)) .filter_map(|ty| ty.ty_vid()) .map(|vid| self.root_var(vid)) @@ -284,8 +284,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // For each diverging variable, figure out whether it can // reach a member of N. If so, it falls back to `()`. Else // `!`. - let mut diverging_fallback = FxHashMap::default(); - diverging_fallback.reserve(diverging_vids.len()); + let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len()); for &diverging_vid in &diverging_vids { let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); @@ -293,14 +292,19 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .depth_first_search(root_vid) .any(|n| roots_reachable_from_non_diverging.visited(n)); - let mut found_infer_var_info = ty::InferVarInfo { self_in_trait: false, output: false }; + let infer_var_infos: UnordBag<_> = self + .inh + .infer_var_info + .borrow() + .items() + .filter(|&(vid, _)| self.infcx.root_var(*vid) == root_vid) + .map(|(_, info)| *info) + .collect(); - for (vid, info) in self.inh.infer_var_info.borrow().iter() { - if self.infcx.root_var(*vid) == root_vid { - found_infer_var_info.self_in_trait |= info.self_in_trait; - found_infer_var_info.output |= info.output; - } - } + let found_infer_var_info = ty::InferVarInfo { + self_in_trait: infer_var_infos.items().any(|info| info.self_in_trait), + output: infer_var_infos.items().any(|info| info.output), + }; if found_infer_var_info.self_in_trait && found_infer_var_info.output { // This case falls back to () to ensure that the code pattern in diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs index b84c49186495d..b059db23bb4d0 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs @@ -6,7 +6,7 @@ use hir::{ intravisit::{self, Visitor}, Body, Expr, ExprKind, Guard, HirId, LoopIdError, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_index::IndexVec; use rustc_infer::infer::InferCtxt; @@ -28,7 +28,7 @@ pub(super) fn build_control_flow_graph<'tcx>( consumed_borrowed_places: ConsumedAndBorrowedPlaces, body: &'tcx Body<'tcx>, num_exprs: usize, -) -> (DropRangesBuilder, FxHashSet) { +) -> (DropRangesBuilder, UnordSet) { let mut drop_range_visitor = DropRangeVisitor::new( infcx, typeck_results, @@ -528,7 +528,7 @@ impl DropRangesBuilder { hir: Map<'_>, num_exprs: usize, ) -> Self { - let mut tracked_value_map = FxHashMap::<_, TrackedValueIndex>::default(); + let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default(); let mut next = <_>::from(0u32); for value in tracked_values { for_each_consumable(hir, value, |value| { diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs index ecafbd668e22d..e01dcf83a3805 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs @@ -17,7 +17,7 @@ use self::record_consumed_borrow::find_consumed_and_borrowed; use crate::FnCtxt; use hir::def_id::DefId; use hir::{Body, HirId, HirIdMap, Node}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -63,7 +63,7 @@ pub fn compute_drop_ranges<'a, 'tcx>( // If drop range tracking is not enabled, skip all the analysis and produce an // empty set of DropRanges. DropRanges { - tracked_value_map: FxHashMap::default(), + tracked_value_map: UnordMap::default(), nodes: IndexVec::new(), borrowed_temporaries: None, } @@ -182,9 +182,9 @@ impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue { } pub struct DropRanges { - tracked_value_map: FxHashMap, + tracked_value_map: UnordMap, nodes: IndexVec, - borrowed_temporaries: Option>, + borrowed_temporaries: Option>, } impl DropRanges { @@ -227,7 +227,7 @@ struct DropRangesBuilder { /// (see NodeInfo::drop_state). The hir_id_map field stores the mapping /// from HirIds to the HirIdIndex that is used to represent that value in /// bitvector. - tracked_value_map: FxHashMap, + tracked_value_map: UnordMap, /// When building the control flow graph, we don't always know the /// post-order index of the target node at the point we encounter it. diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs index 8ab0bd535d6fd..50a3bbf49d510 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -4,7 +4,7 @@ use crate::{ FnCtxt, }; use hir::{def_id::DefId, Body, HirId, HirIdMap}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::{fx::FxIndexSet, unord::UnordSet}; use rustc_hir as hir; use rustc_middle::ty::{ParamEnv, TyCtxt}; use rustc_middle::{ @@ -30,13 +30,13 @@ pub(super) struct ConsumedAndBorrowedPlaces { /// /// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is /// not considered a drop of `x`, although it would be a drop of `x.y`. - pub(super) consumed: HirIdMap>, + pub(super) consumed: HirIdMap>, /// A set of hir-ids of values or variables that are borrowed at some point within the body. - pub(super) borrowed: FxHashSet, + pub(super) borrowed: UnordSet, /// A set of hir-ids of values or variables that are borrowed at some point within the body. - pub(super) borrowed_temporaries: FxHashSet, + pub(super) borrowed_temporaries: UnordSet, } /// Works with ExprUseVisitor to find interesting values for the drop range analysis. diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index d5619af2aae17..7064484a40ff0 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -1,6 +1,6 @@ use super::callee::DeferredCallResolution; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::HirIdMap; @@ -61,9 +61,9 @@ pub struct Inherited<'tcx> { /// Whenever we introduce an adjustment from `!` into a type variable, /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. - pub(super) diverging_type_vars: RefCell>>, + pub(super) diverging_type_vars: RefCell>>, - pub(super) infer_var_info: RefCell>, + pub(super) infer_var_info: RefCell>, } impl<'tcx> Deref for Inherited<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 862430f5eb1cb..b1130430b3993 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -6,7 +6,6 @@ #![feature(min_specialization)] #![feature(control_flow_enum)] #![feature(option_as_slice)] -#![allow(rustc::potential_query_instability)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7bdbcc56da4eb..a30e6479ca6fe 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -7,7 +7,9 @@ use crate::errors::NoAssociatedItem; use crate::Expectation; use crate::FnCtxt; use rustc_ast::ast::Mutability; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::unord::UnordSet; use rustc_errors::StashKey; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, @@ -31,6 +33,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths}; use rustc_middle::ty::IsSuggestable; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::def_id::DefIdSet; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span}; @@ -536,11 +539,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } else if !unsatisfied_predicates.is_empty() { - let mut type_params = FxHashMap::default(); + let mut type_params = FxIndexMap::default(); // Pick out the list of unimplemented traits on the receiver. // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute. - let mut unimplemented_traits = FxHashMap::default(); + let mut unimplemented_traits = FxIndexMap::default(); let mut unimplemented_traits_only = true; for (predicate, _parent_pred, cause) in unsatisfied_predicates { if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) = @@ -606,7 +609,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); type_params .entry(key) - .or_insert_with(FxHashSet::default) + .or_insert_with(UnordSet::default) .insert(obligation.to_owned()); return true; } @@ -680,8 +683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Find all the requirements that come from a local `impl` block. - let mut skip_list: FxHashSet<_> = Default::default(); - let mut spanned_predicates = FxHashMap::default(); + let mut skip_list: UnordSet<_> = Default::default(); + let mut spanned_predicates = FxIndexMap::default(); for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. @@ -723,7 +726,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = self_ty.span.ctxt().outer_expn_data().call_site; let entry = spanned_predicates.entry(span); let entry = entry.or_insert_with(|| { - (FxHashSet::default(), FxHashSet::default(), Vec::new()) + (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(span); entry.1.insert(( @@ -771,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { skip_list.insert(p); let entry = spanned_predicates.entry(self_ty.span); let entry = entry.or_insert_with(|| { - (FxHashSet::default(), FxHashSet::default(), Vec::new()) + (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.2.push(p); if cause_span != *item_span { @@ -806,7 +809,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); let entry = entry.or_insert_with(|| { - (FxHashSet::default(), FxHashSet::default(), Vec::new()) + (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); entry.1.insert((ident.span, "")); @@ -840,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unsatisfied_bounds = true; } - let mut suggested_bounds = FxHashSet::default(); + let mut suggested_bounds = UnordSet::default(); // The requirements that didn't have an `impl` span to show. let mut bound_list = unsatisfied_predicates .iter() @@ -889,8 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ((span, add_where_or_comma), obligations) in type_params.into_iter() { restrict_type_params = true; // #74886: Sort here so that the output is always the same. - let mut obligations = obligations.into_iter().collect::>(); - obligations.sort(); + let obligations = obligations.to_sorted_stable_ord(); err.span_suggestion_verbose( span, format!( @@ -2053,7 +2055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) => Some(def.did()), _ => None, }) - .collect::>(); + .collect::>(); let mut spans: MultiSpan = def_ids .iter() .filter_map(|def_id| { @@ -2669,7 +2671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Nothing, } let ast_generics = hir.get_generics(id.owner.def_id).unwrap(); - let trait_def_ids: FxHashSet = ast_generics + let trait_def_ids: DefIdSet = ast_generics .bounds_for_param(def_id) .flat_map(|bp| bp.bounds.iter()) .filter_map(|bound| bound.trait_ref()?.trait_def_id()) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 93ef0d6ff532e..14c073707e63d 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -33,6 +33,7 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; +use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -48,7 +49,7 @@ use rustc_span::sym; use rustc_span::{BytePos, Pos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_target::abi::FIRST_VARIANT; use std::iter; @@ -910,19 +911,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Combines all the reasons for 2229 migrations fn compute_2229_migrations_reasons( &self, - auto_trait_reasons: FxHashSet<&'static str>, + auto_trait_reasons: UnordSet<&'static str>, drop_order: bool, ) -> MigrationWarningReason { - let mut reasons = MigrationWarningReason::default(); - - reasons.auto_traits.extend(auto_trait_reasons); - reasons.drop_order = drop_order; - - // `auto_trait_reasons` are in hashset order, so sort them to put the - // diagnostics we emit later in a cross-platform-consistent order. - reasons.auto_traits.sort_unstable(); - - reasons + MigrationWarningReason { + auto_traits: auto_trait_reasons.to_sorted_stable_ord(), + drop_order, + } } /// Figures out the list of root variables (and their types) that aren't completely @@ -936,7 +931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, var_hir_id: hir::HirId, closure_clause: hir::CaptureBy, - ) -> Option>> { + ) -> Option>> { let auto_traits_def_id = vec![ self.tcx.lang_items().clone_trait(), self.tcx.lang_items().sync_trait(), @@ -981,7 +976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })); } - let mut problematic_captures = FxHashMap::default(); + let mut problematic_captures = FxIndexMap::default(); // Check whether captured fields also implement the trait for capture in root_var_min_capture_list.iter() { let ty = apply_capture_kind_on_capture_ty( @@ -1001,7 +996,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })); } - let mut capture_problems = FxHashSet::default(); + let mut capture_problems = UnordSet::default(); // Checks if for any of the auto traits, one or more trait is implemented // by the root variable but not by the capture @@ -1047,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, closure_clause: hir::CaptureBy, var_hir_id: hir::HirId, - ) -> Option> { + ) -> Option> { let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id)) { @@ -1069,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match closure_clause { // Only migrate if closure is a move closure hir::CaptureBy::Value => { - let mut diagnostics_info = FxHashSet::default(); + let mut diagnostics_info = FxIndexSet::default(); let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar"); let upvar = upvars[&var_hir_id]; @@ -1085,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?root_var_min_capture_list); let mut projections_list = Vec::new(); - let mut diagnostics_info = FxHashSet::default(); + let mut diagnostics_info = FxIndexSet::default(); for captured_place in root_var_min_capture_list.iter() { match captured_place.info.capture_kind { @@ -1155,7 +1150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut need_migrations = Vec::new(); - let mut auto_trait_migration_reasons = FxHashSet::default(); + let mut auto_trait_migration_reasons = UnordSet::default(); let mut drop_migration_needed = false; // Perform auto-trait analysis @@ -1167,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { diagnostics_info } else { - FxHashMap::default() + FxIndexMap::default() }; let drop_reorder_diagnostic = if let Some(diagnostics_info) = self @@ -1181,7 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { drop_migration_needed = true; diagnostics_info } else { - FxHashSet::default() + FxIndexSet::default() }; // Combine all the captures responsible for needing migrations into one HashSet @@ -1198,7 +1193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) { reasons.clone() } else { - FxHashSet::default() + UnordSet::default() }; // Check if migration is needed because of drop reorder as a result of that capture @@ -1206,7 +1201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Combine all the reasons of why the root variable should be captured as a result of // auto trait implementation issues - auto_trait_migration_reasons.extend(capture_trait_reasons.iter().copied()); + auto_trait_migration_reasons.extend_unord(capture_trait_reasons.items().copied()); diagnostics_info.push(MigrationLintNote { captures_info, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 10645753609a0..eef2b835cbbf7 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -4,17 +4,14 @@ use crate::FnCtxt; use hir::def_id::LocalDefId; -use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc_middle::hir::place::Place as HirPlace; -use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -376,66 +373,75 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn eval_closure_size(&mut self) { - let mut res: FxHashMap> = Default::default(); - for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() { - let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); - - let data = self.resolve(*data, &closure_hir_id); - - res.insert(closure_def_id, data); - } - - self.typeck_results.closure_size_eval = res; + self.tcx().with_stable_hashing_context(|ref hcx| { + let fcx_typeck_results = self.fcx.typeck_results.borrow(); + + self.typeck_results.closure_size_eval = fcx_typeck_results + .closure_size_eval + .to_sorted(hcx, false) + .into_iter() + .map(|(&closure_def_id, data)| { + let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); + let data = self.resolve(*data, &closure_hir_id); + (closure_def_id, data) + }) + .collect(); + }) } - fn visit_min_capture_map(&mut self) { - let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher( - self.fcx.typeck_results.borrow().closure_min_captures.len(), - Default::default(), - ); - for (&closure_def_id, root_min_captures) in - self.fcx.typeck_results.borrow().closure_min_captures.iter() - { - let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher( - root_min_captures.len(), - Default::default(), - ); - for (var_hir_id, min_list) in root_min_captures.iter() { - let min_list_wb = min_list - .iter() - .map(|captured_place| { - let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| { - self.tcx().hir().local_def_id_to_hir_id(closure_def_id) - }); - - self.resolve(captured_place.clone(), &locatable) - }) - .collect(); - root_var_map_wb.insert(*var_hir_id, min_list_wb); - } - min_captures_wb.insert(closure_def_id, root_var_map_wb); - } - self.typeck_results.closure_min_captures = min_captures_wb; + fn visit_min_capture_map(&mut self) { + self.tcx().with_stable_hashing_context(|ref hcx| { + let fcx_typeck_results = self.fcx.typeck_results.borrow(); + + self.typeck_results.closure_min_captures = fcx_typeck_results + .closure_min_captures + .to_sorted(hcx, false) + .into_iter() + .map(|(&closure_def_id, root_min_captures)| { + let root_var_map_wb = root_min_captures + .iter() + .map(|(var_hir_id, min_list)| { + let min_list_wb = min_list + .iter() + .map(|captured_place| { + let locatable = + captured_place.info.path_expr_id.unwrap_or_else(|| { + self.tcx().hir().local_def_id_to_hir_id(closure_def_id) + }); + self.resolve(captured_place.clone(), &locatable) + }) + .collect(); + (*var_hir_id, min_list_wb) + }) + .collect(); + (closure_def_id, root_var_map_wb) + }) + .collect(); + }) } fn visit_fake_reads_map(&mut self) { - let mut resolved_closure_fake_reads: FxHashMap< - LocalDefId, - Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>, - > = Default::default(); - for (&closure_def_id, fake_reads) in - self.fcx.typeck_results.borrow().closure_fake_reads.iter() - { - let mut resolved_fake_reads = Vec::<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>::new(); - for (place, cause, hir_id) in fake_reads.iter() { - let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); - - let resolved_fake_read = self.resolve(place.clone(), &locatable); - resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id)); - } - resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads); - } - self.typeck_results.closure_fake_reads = resolved_closure_fake_reads; + self.tcx().with_stable_hashing_context(move |ref hcx| { + let fcx_typeck_results = self.fcx.typeck_results.borrow(); + + self.typeck_results.closure_fake_reads = fcx_typeck_results + .closure_fake_reads + .to_sorted(hcx, true) + .into_iter() + .map(|(&closure_def_id, fake_reads)| { + let resolved_fake_reads = fake_reads + .iter() + .map(|(place, cause, hir_id)| { + let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id); + let resolved_fake_read = self.resolve(place.clone(), &locatable); + (resolved_fake_read, *cause, *hir_id) + }) + .collect(); + + (closure_def_id, resolved_fake_reads) + }) + .collect(); + }); } fn visit_closures(&mut self) { @@ -540,10 +546,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner); self.typeck_results.generator_interior_types = fcx_typeck_results.generator_interior_types.clone(); - for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.iter() { - let predicates = self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id)); - self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates); - } + self.tcx().with_stable_hashing_context(move |ref hcx| { + for (&expr_def_id, predicates) in + fcx_typeck_results.generator_interior_predicates.to_sorted(hcx, false).into_iter() + { + let predicates = + self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id)); + self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates); + } + }) } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 10712e1468679..c50c5e6f701cd 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -10,7 +10,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; -use rustc_hir::Node; +use rustc_hir::{HirIdMap, Node}; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_span::{Span, DUMMY_SP}; @@ -228,7 +228,7 @@ pub struct ScopeTree { /// and not the enclosing *statement*. Expressions that are not present in this /// table are not rvalue candidates. The set of rvalue candidates is computed /// during type check based on a traversal of the AST. - pub rvalue_candidates: FxHashMap, + pub rvalue_candidates: HirIdMap, /// If there are any `yield` nested within a scope, this map /// stores the `Span` of the last one and its index in the diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index bc9273745491b..91eefa2c1251f 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -6,9 +6,10 @@ use crate::{mir, ty}; use std::fmt::Write; use crate::query::Providers; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, LangItem}; +use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; @@ -56,12 +57,9 @@ pub enum UpvarCapture { ByRef(BorrowKind), } -pub type UpvarListMap = FxHashMap>; -pub type UpvarCaptureMap = FxHashMap; - /// Given the closure DefId this map provides a map of root variables to minimum /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure. -pub type MinCaptureInformationMap<'tcx> = FxHashMap>; +pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap>; /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`. /// Used to track the minimum set of `Place`s that need to be captured to support all diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c8ad9bd1830f7..f23ea986d5594 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -82,8 +82,7 @@ pub use self::binding::BindingMode::*; pub use self::closure::{ is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, - RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, - CAPTURE_STRUCT_LOCAL, + RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index e79b79a25aec9..17eabec257e93 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -1,12 +1,12 @@ use crate::middle::region::{Scope, ScopeData, ScopeTree}; -use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use rustc_hir::ItemLocalMap; /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)] pub struct RvalueScopes { - map: FxHashMap>, + map: ItemLocalMap>, } impl RvalueScopes { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index e85afeb4b6eef..3a63e28d97ebf 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -7,8 +7,10 @@ use crate::{ GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts, }, }; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_data_structures::unord::{UnordItems, UnordSet}; +use rustc_data_structures::{ + fx::FxIndexMap, + unord::{UnordItems, UnordSet}, +}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::{ @@ -180,7 +182,7 @@ pub struct TypeckResults<'tcx> { /// we never capture `t`. This becomes an issue when we build MIR as we require /// information on `t` in order to create place `t.0` and `t.1`. We can solve this /// issue by fake reading `t`. - pub closure_fake_reads: FxHashMap, FakeReadCause, hir::HirId)>>, + pub closure_fake_reads: LocalDefIdMap, FakeReadCause, hir::HirId)>>, /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions /// by applying extended parameter rules. @@ -194,7 +196,7 @@ pub struct TypeckResults<'tcx> { /// Stores the predicates that apply on generator witness types. /// formatting modified file tests/ui/generator/retain-resume-ref.rs pub generator_interior_predicates: - FxHashMap, ObligationCause<'tcx>)>>, + LocalDefIdMap, ObligationCause<'tcx>)>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) /// as `&[u8]`, depending on the pattern in which they are used. @@ -204,7 +206,7 @@ pub struct TypeckResults<'tcx> { /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` /// on closure size. - pub closure_size_eval: FxHashMap>, + pub closure_size_eval: LocalDefIdMap>, /// Container types and field indices of `offset_of!` expressions offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec)>, From 457b787a524e87a11d715ec26a24e68c8cf272d9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 10 Jul 2023 13:02:52 +0200 Subject: [PATCH 2/2] Introduce ExtentUnord trait for collections that can safely consume UnordItems. --- compiler/rustc_data_structures/src/unord.rs | 52 ++++++++++++------- .../rustc_hir_analysis/src/check_unused.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 3 +- .../rustc_middle/src/ty/typeck_results.rs | 4 +- .../rustc_mir_transform/src/check_unsafety.rs | 2 +- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index ec779854f361f..47c56eba7adc8 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -168,6 +168,14 @@ impl> UnordItems { } } +/// A marker trait specifying that `Self` can consume `UnordItems<_>` without +/// exposing any internal ordering. +/// +/// Note: right now this is just a marker trait. It could be extended to contain +/// some useful, common methods though, like `len`, `clear`, or the various +/// kinds of `to_sorted`. +trait UnordCollection {} + /// This is a set collection type that tries very hard to not expose /// any internal iteration. This is a useful property when trying to /// uphold the determinism invariants imposed by the query system. @@ -182,6 +190,8 @@ pub struct UnordSet { inner: FxHashSet, } +impl UnordCollection for UnordSet {} + impl Default for UnordSet { #[inline] fn default() -> Self { @@ -285,16 +295,28 @@ impl UnordSet { to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x) } - // We can safely extend this UnordSet from a set of unordered values because that - // won't expose the internal ordering anywhere. #[inline] - pub fn extend_unord>(&mut self, items: UnordItems) { - self.inner.extend(items.0) + pub fn clear(&mut self) { + self.inner.clear(); } +} + +pub trait ExtendUnord { + /// Extend this unord collection with the given `UnordItems`. + /// This method is called `extend_unord` instead of just `extend` so it + /// does not conflict with `Extend::extend`. Otherwise there would be many + /// places where the two methods would have to be explicitly disambiguated + /// via UFCS. + fn extend_unord>(&mut self, items: UnordItems); +} +// Note: it is important that `C` implements `UnordCollection` in addition to +// `Extend`, otherwise this impl would leak the internal iteration order of +// `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`. +impl + UnordCollection, T> ExtendUnord for C { #[inline] - pub fn clear(&mut self) { - self.inner.clear(); + fn extend_unord>(&mut self, items: UnordItems) { + self.extend(items.0) } } @@ -345,6 +367,8 @@ pub struct UnordMap { inner: FxHashMap, } +impl UnordCollection for UnordMap {} + impl Default for UnordMap { #[inline] fn default() -> Self { @@ -445,13 +469,6 @@ impl UnordMap { UnordItems(self.inner.into_iter()) } - // We can safely extend this UnordMap from a set of unordered values because that - // won't expose the internal ordering anywhere. - #[inline] - pub fn extend>(&mut self, items: UnordItems<(K, V), I>) { - self.inner.extend(items.0) - } - /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`). /// /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or @@ -571,15 +588,10 @@ impl UnordBag { pub fn into_items(self) -> UnordItems> { UnordItems(self.inner.into_iter()) } - - // We can safely extend this UnordSet from a set of unordered values because that - // won't expose the internal ordering anywhere. - #[inline] - pub fn extend>(&mut self, items: UnordItems) { - self.inner.extend(items.0) - } } +impl UnordCollection for UnordBag {} + impl Extend for UnordBag { fn extend>(&mut self, iter: I) { self.inner.extend(iter) diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 3471d5f1e7724..5318e637fc778 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::unord::UnordSet; +use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 14c073707e63d..a3838275dc5cd 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -33,7 +33,7 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; -use rustc_data_structures::unord::UnordSet; +use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index eef2b835cbbf7..fab6090ff195a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -4,6 +4,7 @@ use crate::FnCtxt; use hir::def_id::LocalDefId; +use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; @@ -526,7 +527,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let fcx_typeck_results = self.fcx.typeck_results.borrow(); assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner); - self.typeck_results.user_provided_sigs.extend( + self.typeck_results.user_provided_sigs.extend_unord( fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| { if cfg!(debug_assertions) && c_sig.has_infer() { span_bug!( diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 3a63e28d97ebf..9c25c01b05676 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -9,7 +9,7 @@ use crate::{ }; use rustc_data_structures::{ fx::FxIndexMap, - unord::{UnordItems, UnordSet}, + unord::{ExtendUnord, UnordItems, UnordSet}, }; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -635,7 +635,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { &mut self, items: UnordItems<(hir::HirId, V), impl Iterator>, ) { - self.data.extend(items.map(|(id, value)| { + self.data.extend_unord(items.map(|(id, value)| { validate_hir_id_for_typeck_results(self.hir_owner, id); (id.local_id, value) })) diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 70812761e88d6..58e9786ec1a54 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::unord::{UnordItems, UnordSet}; +use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId};