Skip to content

Commit df5c2cf

Browse files
committed
Auto merge of #113328 - michaelwoerister:no_hashmap_in_typeck, r=cjgillot,lcnr
Enable potential_query_instability lint in rustc_hir_typeck. Fix linting errors by using `FxIndex(Map|Set)` and `Unord(Map|Set)` as appropriate. Part of [MCP 533](rust-lang/compiler-team#533). I really like the `potential_query_instability` lint! r? `@lcnr`
2 parents 320b412 + 457b787 commit df5c2cf

File tree

17 files changed

+212
-172
lines changed

17 files changed

+212
-172
lines changed

compiler/rustc_data_structures/src/unord.rs

+51-22
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::{
3131
///
3232
/// It's still possible to do the same thing with an `Fn` by using interior mutability,
3333
/// but the chance of doing it accidentally is reduced.
34+
#[derive(Clone)]
3435
pub struct UnordItems<T, I: Iterator<Item = T>>(I);
3536

3637
impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
@@ -167,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
167168
}
168169
}
169170

171+
/// A marker trait specifying that `Self` can consume `UnordItems<_>` without
172+
/// exposing any internal ordering.
173+
///
174+
/// Note: right now this is just a marker trait. It could be extended to contain
175+
/// some useful, common methods though, like `len`, `clear`, or the various
176+
/// kinds of `to_sorted`.
177+
trait UnordCollection {}
178+
170179
/// This is a set collection type that tries very hard to not expose
171180
/// any internal iteration. This is a useful property when trying to
172181
/// uphold the determinism invariants imposed by the query system.
@@ -181,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
181190
inner: FxHashSet<V>,
182191
}
183192

193+
impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
194+
184195
impl<V: Eq + Hash> Default for UnordSet<V> {
185196
#[inline]
186197
fn default() -> Self {
@@ -194,6 +205,11 @@ impl<V: Eq + Hash> UnordSet<V> {
194205
Self { inner: Default::default() }
195206
}
196207

208+
#[inline]
209+
pub fn with_capacity(capacity: usize) -> Self {
210+
Self { inner: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) }
211+
}
212+
197213
#[inline]
198214
pub fn len(&self) -> usize {
199215
self.inner.len()
@@ -258,9 +274,9 @@ impl<V: Eq + Hash> UnordSet<V> {
258274
#[inline]
259275
pub fn to_sorted_stable_ord(&self) -> Vec<V>
260276
where
261-
V: Ord + StableOrd + Copy,
277+
V: Ord + StableOrd + Clone,
262278
{
263-
let mut items: Vec<V> = self.inner.iter().copied().collect();
279+
let mut items: Vec<V> = self.inner.iter().cloned().collect();
264280
items.sort_unstable();
265281
items
266282
}
@@ -279,16 +295,28 @@ impl<V: Eq + Hash> UnordSet<V> {
279295
to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
280296
}
281297

282-
// We can safely extend this UnordSet from a set of unordered values because that
283-
// won't expose the internal ordering anywhere.
284298
#[inline]
285-
pub fn extend_unord<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
286-
self.inner.extend(items.0)
299+
pub fn clear(&mut self) {
300+
self.inner.clear();
287301
}
302+
}
303+
304+
pub trait ExtendUnord<T> {
305+
/// Extend this unord collection with the given `UnordItems`.
306+
/// This method is called `extend_unord` instead of just `extend` so it
307+
/// does not conflict with `Extend::extend`. Otherwise there would be many
308+
/// places where the two methods would have to be explicitly disambiguated
309+
/// via UFCS.
310+
fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>);
311+
}
288312

313+
// Note: it is important that `C` implements `UnordCollection` in addition to
314+
// `Extend`, otherwise this impl would leak the internal iteration order of
315+
// `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`.
316+
impl<C: Extend<T> + UnordCollection, T> ExtendUnord<T> for C {
289317
#[inline]
290-
pub fn clear(&mut self) {
291-
self.inner.clear();
318+
fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>) {
319+
self.extend(items.0)
292320
}
293321
}
294322

@@ -312,6 +340,12 @@ impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
312340
}
313341
}
314342

343+
impl<V: Hash + Eq, I: Iterator<Item = V>> From<UnordItems<V, I>> for UnordSet<V> {
344+
fn from(value: UnordItems<V, I>) -> Self {
345+
UnordSet { inner: FxHashSet::from_iter(value.0) }
346+
}
347+
}
348+
315349
impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
316350
#[inline]
317351
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
@@ -333,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
333367
inner: FxHashMap<K, V>,
334368
}
335369

370+
impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
371+
336372
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
337373
#[inline]
338374
fn default() -> Self {
@@ -362,6 +398,11 @@ impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> fo
362398
}
363399

364400
impl<K: Eq + Hash, V> UnordMap<K, V> {
401+
#[inline]
402+
pub fn with_capacity(capacity: usize) -> Self {
403+
Self { inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) }
404+
}
405+
365406
#[inline]
366407
pub fn len(&self) -> usize {
367408
self.inner.len()
@@ -428,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
428469
UnordItems(self.inner.into_iter())
429470
}
430471

431-
// We can safely extend this UnordMap from a set of unordered values because that
432-
// won't expose the internal ordering anywhere.
433-
#[inline]
434-
pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
435-
self.inner.extend(items.0)
436-
}
437-
438472
/// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
439473
///
440474
/// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
@@ -554,15 +588,10 @@ impl<V> UnordBag<V> {
554588
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
555589
UnordItems(self.inner.into_iter())
556590
}
557-
558-
// We can safely extend this UnordSet from a set of unordered values because that
559-
// won't expose the internal ordering anywhere.
560-
#[inline]
561-
pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
562-
self.inner.extend(items.0)
563-
}
564591
}
565592

593+
impl<T> UnordCollection for UnordBag<T> {}
594+
566595
impl<T> Extend<T> for UnordBag<T> {
567596
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
568597
self.inner.extend(iter)

compiler/rustc_hir_analysis/src/check_unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::unord::UnordSet;
1+
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
22
use rustc_hir::def::DefKind;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_middle::ty::TyCtxt;

compiler/rustc_hir_typeck/src/fallback.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::FnCtxt;
22
use rustc_data_structures::{
3-
fx::{FxHashMap, FxHashSet},
43
graph::WithSuccessors,
54
graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
5+
unord::{UnordBag, UnordMap, UnordSet},
66
};
77
use rustc_middle::ty::{self, Ty};
88

@@ -83,7 +83,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
8383
fn fallback_if_possible(
8484
&self,
8585
ty: Ty<'tcx>,
86-
diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
86+
diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
8787
) {
8888
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
8989
// is an unsolved variable, and we determine its fallback
@@ -193,7 +193,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
193193
fn calculate_diverging_fallback(
194194
&self,
195195
unsolved_variables: &[Ty<'tcx>],
196-
) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
196+
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
197197
debug!("calculate_diverging_fallback({:?})", unsolved_variables);
198198

199199
// Construct a coercion graph where an edge `A -> B` indicates
@@ -210,10 +210,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
210210
//
211211
// These variables are the ones that are targets for fallback to
212212
// either `!` or `()`.
213-
let diverging_roots: FxHashSet<ty::TyVid> = self
213+
let diverging_roots: UnordSet<ty::TyVid> = self
214214
.diverging_type_vars
215215
.borrow()
216-
.iter()
216+
.items()
217217
.map(|&ty| self.shallow_resolve(ty))
218218
.filter_map(|ty| ty.ty_vid())
219219
.map(|vid| self.root_var(vid))
@@ -284,23 +284,27 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
284284
// For each diverging variable, figure out whether it can
285285
// reach a member of N. If so, it falls back to `()`. Else
286286
// `!`.
287-
let mut diverging_fallback = FxHashMap::default();
288-
diverging_fallback.reserve(diverging_vids.len());
287+
let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
289288
for &diverging_vid in &diverging_vids {
290289
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
291290
let root_vid = self.root_var(diverging_vid);
292291
let can_reach_non_diverging = coercion_graph
293292
.depth_first_search(root_vid)
294293
.any(|n| roots_reachable_from_non_diverging.visited(n));
295294

296-
let mut found_infer_var_info = ty::InferVarInfo { self_in_trait: false, output: false };
295+
let infer_var_infos: UnordBag<_> = self
296+
.inh
297+
.infer_var_info
298+
.borrow()
299+
.items()
300+
.filter(|&(vid, _)| self.infcx.root_var(*vid) == root_vid)
301+
.map(|(_, info)| *info)
302+
.collect();
297303

298-
for (vid, info) in self.inh.infer_var_info.borrow().iter() {
299-
if self.infcx.root_var(*vid) == root_vid {
300-
found_infer_var_info.self_in_trait |= info.self_in_trait;
301-
found_infer_var_info.output |= info.output;
302-
}
303-
}
304+
let found_infer_var_info = ty::InferVarInfo {
305+
self_in_trait: infer_var_infos.items().any(|info| info.self_in_trait),
306+
output: infer_var_infos.items().any(|info| info.output),
307+
};
304308

305309
if found_infer_var_info.self_in_trait && found_infer_var_info.output {
306310
// This case falls back to () to ensure that the code pattern in

compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use hir::{
66
intravisit::{self, Visitor},
77
Body, Expr, ExprKind, Guard, HirId, LoopIdError,
88
};
9-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9+
use rustc_data_structures::unord::{UnordMap, UnordSet};
1010
use rustc_hir as hir;
1111
use rustc_index::IndexVec;
1212
use rustc_infer::infer::InferCtxt;
@@ -28,7 +28,7 @@ pub(super) fn build_control_flow_graph<'tcx>(
2828
consumed_borrowed_places: ConsumedAndBorrowedPlaces,
2929
body: &'tcx Body<'tcx>,
3030
num_exprs: usize,
31-
) -> (DropRangesBuilder, FxHashSet<HirId>) {
31+
) -> (DropRangesBuilder, UnordSet<HirId>) {
3232
let mut drop_range_visitor = DropRangeVisitor::new(
3333
infcx,
3434
typeck_results,
@@ -528,7 +528,7 @@ impl DropRangesBuilder {
528528
hir: Map<'_>,
529529
num_exprs: usize,
530530
) -> Self {
531-
let mut tracked_value_map = FxHashMap::<_, TrackedValueIndex>::default();
531+
let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default();
532532
let mut next = <_>::from(0u32);
533533
for value in tracked_values {
534534
for_each_consumable(hir, value, |value| {

compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use self::record_consumed_borrow::find_consumed_and_borrowed;
1717
use crate::FnCtxt;
1818
use hir::def_id::DefId;
1919
use hir::{Body, HirId, HirIdMap, Node};
20-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
20+
use rustc_data_structures::unord::{UnordMap, UnordSet};
2121
use rustc_hir as hir;
2222
use rustc_index::bit_set::BitSet;
2323
use rustc_index::IndexVec;
@@ -63,7 +63,7 @@ pub fn compute_drop_ranges<'a, 'tcx>(
6363
// If drop range tracking is not enabled, skip all the analysis and produce an
6464
// empty set of DropRanges.
6565
DropRanges {
66-
tracked_value_map: FxHashMap::default(),
66+
tracked_value_map: UnordMap::default(),
6767
nodes: IndexVec::new(),
6868
borrowed_temporaries: None,
6969
}
@@ -182,9 +182,9 @@ impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue {
182182
}
183183

184184
pub struct DropRanges {
185-
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
185+
tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
186186
nodes: IndexVec<PostOrderId, NodeInfo>,
187-
borrowed_temporaries: Option<FxHashSet<HirId>>,
187+
borrowed_temporaries: Option<UnordSet<HirId>>,
188188
}
189189

190190
impl DropRanges {
@@ -227,7 +227,7 @@ struct DropRangesBuilder {
227227
/// (see NodeInfo::drop_state). The hir_id_map field stores the mapping
228228
/// from HirIds to the HirIdIndex that is used to represent that value in
229229
/// bitvector.
230-
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
230+
tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
231231

232232
/// When building the control flow graph, we don't always know the
233233
/// post-order index of the target node at the point we encounter it.

compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
FnCtxt,
55
};
66
use hir::{def_id::DefId, Body, HirId, HirIdMap};
7-
use rustc_data_structures::fx::FxHashSet;
7+
use rustc_data_structures::{fx::FxIndexSet, unord::UnordSet};
88
use rustc_hir as hir;
99
use rustc_middle::ty::{ParamEnv, TyCtxt};
1010
use rustc_middle::{
@@ -30,13 +30,13 @@ pub(super) struct ConsumedAndBorrowedPlaces {
3030
///
3131
/// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
3232
/// not considered a drop of `x`, although it would be a drop of `x.y`.
33-
pub(super) consumed: HirIdMap<FxHashSet<TrackedValue>>,
33+
pub(super) consumed: HirIdMap<FxIndexSet<TrackedValue>>,
3434

3535
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
36-
pub(super) borrowed: FxHashSet<TrackedValue>,
36+
pub(super) borrowed: UnordSet<TrackedValue>,
3737

3838
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
39-
pub(super) borrowed_temporaries: FxHashSet<HirId>,
39+
pub(super) borrowed_temporaries: UnordSet<HirId>,
4040
}
4141

4242
/// Works with ExprUseVisitor to find interesting values for the drop range analysis.

compiler/rustc_hir_typeck/src/inherited.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::callee::DeferredCallResolution;
22

3-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3+
use rustc_data_structures::unord::{UnordMap, UnordSet};
44
use rustc_hir as hir;
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_hir::HirIdMap;
@@ -61,9 +61,9 @@ pub struct Inherited<'tcx> {
6161
/// Whenever we introduce an adjustment from `!` into a type variable,
6262
/// we record that type variable here. This is later used to inform
6363
/// fallback. See the `fallback` module for details.
64-
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
64+
pub(super) diverging_type_vars: RefCell<UnordSet<Ty<'tcx>>>,
6565

66-
pub(super) infer_var_info: RefCell<FxHashMap<ty::TyVid, ty::InferVarInfo>>,
66+
pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, ty::InferVarInfo>>,
6767
}
6868

6969
impl<'tcx> Deref for Inherited<'tcx> {

compiler/rustc_hir_typeck/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#![feature(min_specialization)]
77
#![feature(control_flow_enum)]
88
#![feature(option_as_slice)]
9-
#![allow(rustc::potential_query_instability)]
109
#![recursion_limit = "256"]
1110

1211
#[macro_use]

0 commit comments

Comments
 (0)