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](https://github.com/rust-lang/compiler-team/issues/533). I really like the `potential_query_instability` lint! r? `@lcnr`
This commit is contained in:
commit
df5c2cf9bc
17 changed files with 210 additions and 170 deletions
|
@ -31,6 +31,7 @@ use crate::{
|
||||||
///
|
///
|
||||||
/// It's still possible to do the same thing with an `Fn` by using interior mutability,
|
/// 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.
|
/// but the chance of doing it accidentally is reduced.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UnordItems<T, I: Iterator<Item = T>>(I);
|
pub struct UnordItems<T, I: Iterator<Item = T>>(I);
|
||||||
|
|
||||||
impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
|
impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
|
||||||
|
@ -167,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
/// This is a set collection type that tries very hard to not expose
|
||||||
/// any internal iteration. This is a useful property when trying to
|
/// any internal iteration. This is a useful property when trying to
|
||||||
/// uphold the determinism invariants imposed by the query system.
|
/// uphold the determinism invariants imposed by the query system.
|
||||||
|
@ -181,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
|
||||||
inner: FxHashSet<V>,
|
inner: FxHashSet<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
|
||||||
|
|
||||||
impl<V: Eq + Hash> Default for UnordSet<V> {
|
impl<V: Eq + Hash> Default for UnordSet<V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -194,6 +205,11 @@ impl<V: Eq + Hash> UnordSet<V> {
|
||||||
Self { inner: Default::default() }
|
Self { inner: Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self { inner: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) }
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.inner.len()
|
self.inner.len()
|
||||||
|
@ -258,9 +274,9 @@ impl<V: Eq + Hash> UnordSet<V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_sorted_stable_ord(&self) -> Vec<V>
|
pub fn to_sorted_stable_ord(&self) -> Vec<V>
|
||||||
where
|
where
|
||||||
V: Ord + StableOrd + Copy,
|
V: Ord + StableOrd + Clone,
|
||||||
{
|
{
|
||||||
let mut items: Vec<V> = self.inner.iter().copied().collect();
|
let mut items: Vec<V> = self.inner.iter().cloned().collect();
|
||||||
items.sort_unstable();
|
items.sort_unstable();
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
@ -279,19 +295,31 @@ impl<V: Eq + Hash> UnordSet<V> {
|
||||||
to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
|
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<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
|
|
||||||
self.inner.extend(items.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.inner.clear();
|
self.inner.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ExtendUnord<T> {
|
||||||
|
/// 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<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<C: Extend<T> + UnordCollection, T> ExtendUnord<T> for C {
|
||||||
|
#[inline]
|
||||||
|
fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>) {
|
||||||
|
self.extend(items.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
|
impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
|
||||||
|
@ -312,6 +340,12 @@ impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Hash + Eq, I: Iterator<Item = V>> From<UnordItems<V, I>> for UnordSet<V> {
|
||||||
|
fn from(value: UnordItems<V, I>) -> Self {
|
||||||
|
UnordSet { inner: FxHashSet::from_iter(value.0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
|
impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
|
||||||
|
@ -333,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
|
||||||
inner: FxHashMap<K, V>,
|
inner: FxHashMap<K, V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
|
||||||
|
|
||||||
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
|
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -362,6 +398,11 @@ impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> fo
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Eq + Hash, V> UnordMap<K, V> {
|
impl<K: Eq + Hash, V> UnordMap<K, V> {
|
||||||
|
#[inline]
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self { inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) }
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.inner.len()
|
self.inner.len()
|
||||||
|
@ -428,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
|
||||||
UnordItems(self.inner.into_iter())
|
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<I: Iterator<Item = (K, V)>>(&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`).
|
/// 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
|
/// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
|
||||||
|
@ -554,15 +588,10 @@ impl<V> UnordBag<V> {
|
||||||
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
|
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
|
||||||
UnordItems(self.inner.into_iter())
|
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<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
|
|
||||||
self.inner.extend(items.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> UnordCollection for UnordBag<T> {}
|
||||||
|
|
||||||
impl<T> Extend<T> for UnordBag<T> {
|
impl<T> Extend<T> for UnordBag<T> {
|
||||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||||
self.inner.extend(iter)
|
self.inner.extend(iter)
|
||||||
|
|
|
@ -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::DefKind;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::FnCtxt;
|
use crate::FnCtxt;
|
||||||
use rustc_data_structures::{
|
use rustc_data_structures::{
|
||||||
fx::{FxHashMap, FxHashSet},
|
|
||||||
graph::WithSuccessors,
|
graph::WithSuccessors,
|
||||||
graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
|
graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
|
||||||
|
unord::{UnordBag, UnordMap, UnordSet},
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
fn fallback_if_possible(
|
fn fallback_if_possible(
|
||||||
&self,
|
&self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
|
diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
|
||||||
) {
|
) {
|
||||||
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
|
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
|
||||||
// is an unsolved variable, and we determine its fallback
|
// is an unsolved variable, and we determine its fallback
|
||||||
|
@ -193,7 +193,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
fn calculate_diverging_fallback(
|
fn calculate_diverging_fallback(
|
||||||
&self,
|
&self,
|
||||||
unsolved_variables: &[Ty<'tcx>],
|
unsolved_variables: &[Ty<'tcx>],
|
||||||
) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
|
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
|
||||||
debug!("calculate_diverging_fallback({:?})", unsolved_variables);
|
debug!("calculate_diverging_fallback({:?})", unsolved_variables);
|
||||||
|
|
||||||
// Construct a coercion graph where an edge `A -> B` indicates
|
// 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
|
// These variables are the ones that are targets for fallback to
|
||||||
// either `!` or `()`.
|
// either `!` or `()`.
|
||||||
let diverging_roots: FxHashSet<ty::TyVid> = self
|
let diverging_roots: UnordSet<ty::TyVid> = self
|
||||||
.diverging_type_vars
|
.diverging_type_vars
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.items()
|
||||||
.map(|&ty| self.shallow_resolve(ty))
|
.map(|&ty| self.shallow_resolve(ty))
|
||||||
.filter_map(|ty| ty.ty_vid())
|
.filter_map(|ty| ty.ty_vid())
|
||||||
.map(|vid| self.root_var(vid))
|
.map(|vid| self.root_var(vid))
|
||||||
|
@ -284,8 +284,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
// For each diverging variable, figure out whether it can
|
// For each diverging variable, figure out whether it can
|
||||||
// reach a member of N. If so, it falls back to `()`. Else
|
// reach a member of N. If so, it falls back to `()`. Else
|
||||||
// `!`.
|
// `!`.
|
||||||
let mut diverging_fallback = FxHashMap::default();
|
let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
|
||||||
diverging_fallback.reserve(diverging_vids.len());
|
|
||||||
for &diverging_vid in &diverging_vids {
|
for &diverging_vid in &diverging_vids {
|
||||||
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
|
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
|
||||||
let root_vid = self.root_var(diverging_vid);
|
let root_vid = self.root_var(diverging_vid);
|
||||||
|
@ -293,14 +292,19 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||||
.depth_first_search(root_vid)
|
.depth_first_search(root_vid)
|
||||||
.any(|n| roots_reachable_from_non_diverging.visited(n));
|
.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() {
|
let found_infer_var_info = ty::InferVarInfo {
|
||||||
if self.infcx.root_var(*vid) == root_vid {
|
self_in_trait: infer_var_infos.items().any(|info| info.self_in_trait),
|
||||||
found_infer_var_info.self_in_trait |= info.self_in_trait;
|
output: infer_var_infos.items().any(|info| info.output),
|
||||||
found_infer_var_info.output |= info.output;
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if found_infer_var_info.self_in_trait && found_infer_var_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
|
// This case falls back to () to ensure that the code pattern in
|
||||||
|
|
|
@ -6,7 +6,7 @@ use hir::{
|
||||||
intravisit::{self, Visitor},
|
intravisit::{self, Visitor},
|
||||||
Body, Expr, ExprKind, Guard, HirId, LoopIdError,
|
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_hir as hir;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
|
@ -28,7 +28,7 @@ pub(super) fn build_control_flow_graph<'tcx>(
|
||||||
consumed_borrowed_places: ConsumedAndBorrowedPlaces,
|
consumed_borrowed_places: ConsumedAndBorrowedPlaces,
|
||||||
body: &'tcx Body<'tcx>,
|
body: &'tcx Body<'tcx>,
|
||||||
num_exprs: usize,
|
num_exprs: usize,
|
||||||
) -> (DropRangesBuilder, FxHashSet<HirId>) {
|
) -> (DropRangesBuilder, UnordSet<HirId>) {
|
||||||
let mut drop_range_visitor = DropRangeVisitor::new(
|
let mut drop_range_visitor = DropRangeVisitor::new(
|
||||||
infcx,
|
infcx,
|
||||||
typeck_results,
|
typeck_results,
|
||||||
|
@ -528,7 +528,7 @@ impl DropRangesBuilder {
|
||||||
hir: Map<'_>,
|
hir: Map<'_>,
|
||||||
num_exprs: usize,
|
num_exprs: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut tracked_value_map = FxHashMap::<_, TrackedValueIndex>::default();
|
let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default();
|
||||||
let mut next = <_>::from(0u32);
|
let mut next = <_>::from(0u32);
|
||||||
for value in tracked_values {
|
for value in tracked_values {
|
||||||
for_each_consumable(hir, value, |value| {
|
for_each_consumable(hir, value, |value| {
|
||||||
|
|
|
@ -17,7 +17,7 @@ use self::record_consumed_borrow::find_consumed_and_borrowed;
|
||||||
use crate::FnCtxt;
|
use crate::FnCtxt;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir::{Body, HirId, HirIdMap, Node};
|
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_hir as hir;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::IndexVec;
|
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
|
// If drop range tracking is not enabled, skip all the analysis and produce an
|
||||||
// empty set of DropRanges.
|
// empty set of DropRanges.
|
||||||
DropRanges {
|
DropRanges {
|
||||||
tracked_value_map: FxHashMap::default(),
|
tracked_value_map: UnordMap::default(),
|
||||||
nodes: IndexVec::new(),
|
nodes: IndexVec::new(),
|
||||||
borrowed_temporaries: None,
|
borrowed_temporaries: None,
|
||||||
}
|
}
|
||||||
|
@ -182,9 +182,9 @@ impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DropRanges {
|
pub struct DropRanges {
|
||||||
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
|
tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
|
||||||
nodes: IndexVec<PostOrderId, NodeInfo>,
|
nodes: IndexVec<PostOrderId, NodeInfo>,
|
||||||
borrowed_temporaries: Option<FxHashSet<HirId>>,
|
borrowed_temporaries: Option<UnordSet<HirId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DropRanges {
|
impl DropRanges {
|
||||||
|
@ -227,7 +227,7 @@ struct DropRangesBuilder {
|
||||||
/// (see NodeInfo::drop_state). The hir_id_map field stores the mapping
|
/// (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
|
/// from HirIds to the HirIdIndex that is used to represent that value in
|
||||||
/// bitvector.
|
/// bitvector.
|
||||||
tracked_value_map: FxHashMap<TrackedValue, TrackedValueIndex>,
|
tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
|
||||||
|
|
||||||
/// When building the control flow graph, we don't always know the
|
/// 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.
|
/// post-order index of the target node at the point we encounter it.
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
FnCtxt,
|
FnCtxt,
|
||||||
};
|
};
|
||||||
use hir::{def_id::DefId, Body, HirId, HirIdMap};
|
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_hir as hir;
|
||||||
use rustc_middle::ty::{ParamEnv, TyCtxt};
|
use rustc_middle::ty::{ParamEnv, TyCtxt};
|
||||||
use rustc_middle::{
|
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
|
/// 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`.
|
/// not considered a drop of `x`, although it would be a drop of `x.y`.
|
||||||
pub(super) consumed: HirIdMap<FxHashSet<TrackedValue>>,
|
pub(super) consumed: HirIdMap<FxIndexSet<TrackedValue>>,
|
||||||
|
|
||||||
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
||||||
pub(super) borrowed: FxHashSet<TrackedValue>,
|
pub(super) borrowed: UnordSet<TrackedValue>,
|
||||||
|
|
||||||
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
/// A set of hir-ids of values or variables that are borrowed at some point within the body.
|
||||||
pub(super) borrowed_temporaries: FxHashSet<HirId>,
|
pub(super) borrowed_temporaries: UnordSet<HirId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Works with ExprUseVisitor to find interesting values for the drop range analysis.
|
/// Works with ExprUseVisitor to find interesting values for the drop range analysis.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::callee::DeferredCallResolution;
|
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 as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::HirIdMap;
|
use rustc_hir::HirIdMap;
|
||||||
|
@ -61,9 +61,9 @@ pub struct Inherited<'tcx> {
|
||||||
/// Whenever we introduce an adjustment from `!` into a type variable,
|
/// Whenever we introduce an adjustment from `!` into a type variable,
|
||||||
/// we record that type variable here. This is later used to inform
|
/// we record that type variable here. This is later used to inform
|
||||||
/// fallback. See the `fallback` module for details.
|
/// fallback. See the `fallback` module for details.
|
||||||
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
|
pub(super) diverging_type_vars: RefCell<UnordSet<Ty<'tcx>>>,
|
||||||
|
|
||||||
pub(super) infer_var_info: RefCell<FxHashMap<ty::TyVid, ty::InferVarInfo>>,
|
pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, ty::InferVarInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Deref for Inherited<'tcx> {
|
impl<'tcx> Deref for Inherited<'tcx> {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
#![feature(option_as_slice)]
|
#![feature(option_as_slice)]
|
||||||
#![allow(rustc::potential_query_instability)]
|
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -7,7 +7,9 @@ use crate::errors::NoAssociatedItem;
|
||||||
use crate::Expectation;
|
use crate::Expectation;
|
||||||
use crate::FnCtxt;
|
use crate::FnCtxt;
|
||||||
use rustc_ast::ast::Mutability;
|
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::StashKey;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
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::print::{with_crate_prefix, with_forced_trimmed_paths};
|
||||||
use rustc_middle::ty::IsSuggestable;
|
use rustc_middle::ty::IsSuggestable;
|
||||||
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
|
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::{kw, sym, Ident};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
|
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() {
|
} 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.
|
// Pick out the list of unimplemented traits on the receiver.
|
||||||
// This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
|
// 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;
|
let mut unimplemented_traits_only = true;
|
||||||
for (predicate, _parent_pred, cause) in unsatisfied_predicates {
|
for (predicate, _parent_pred, cause) in unsatisfied_predicates {
|
||||||
if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) =
|
if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) =
|
||||||
|
@ -606,7 +609,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
type_params
|
type_params
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(FxHashSet::default)
|
.or_insert_with(UnordSet::default)
|
||||||
.insert(obligation.to_owned());
|
.insert(obligation.to_owned());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -680,8 +683,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find all the requirements that come from a local `impl` block.
|
// Find all the requirements that come from a local `impl` block.
|
||||||
let mut skip_list: FxHashSet<_> = Default::default();
|
let mut skip_list: UnordSet<_> = Default::default();
|
||||||
let mut spanned_predicates = FxHashMap::default();
|
let mut spanned_predicates = FxIndexMap::default();
|
||||||
for (p, parent_p, cause) in unsatisfied_predicates {
|
for (p, parent_p, cause) in unsatisfied_predicates {
|
||||||
// Extract the predicate span and parent def id of the cause,
|
// Extract the predicate span and parent def id of the cause,
|
||||||
// if we have one.
|
// 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 span = self_ty.span.ctxt().outer_expn_data().call_site;
|
||||||
let entry = spanned_predicates.entry(span);
|
let entry = spanned_predicates.entry(span);
|
||||||
let entry = entry.or_insert_with(|| {
|
let entry = entry.or_insert_with(|| {
|
||||||
(FxHashSet::default(), FxHashSet::default(), Vec::new())
|
(FxIndexSet::default(), FxIndexSet::default(), Vec::new())
|
||||||
});
|
});
|
||||||
entry.0.insert(span);
|
entry.0.insert(span);
|
||||||
entry.1.insert((
|
entry.1.insert((
|
||||||
|
@ -771,7 +774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
skip_list.insert(p);
|
skip_list.insert(p);
|
||||||
let entry = spanned_predicates.entry(self_ty.span);
|
let entry = spanned_predicates.entry(self_ty.span);
|
||||||
let entry = entry.or_insert_with(|| {
|
let entry = entry.or_insert_with(|| {
|
||||||
(FxHashSet::default(), FxHashSet::default(), Vec::new())
|
(FxIndexSet::default(), FxIndexSet::default(), Vec::new())
|
||||||
});
|
});
|
||||||
entry.2.push(p);
|
entry.2.push(p);
|
||||||
if cause_span != *item_span {
|
if cause_span != *item_span {
|
||||||
|
@ -806,7 +809,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
skip_list.insert(p);
|
skip_list.insert(p);
|
||||||
let entry = spanned_predicates.entry(ident.span);
|
let entry = spanned_predicates.entry(ident.span);
|
||||||
let entry = entry.or_insert_with(|| {
|
let entry = entry.or_insert_with(|| {
|
||||||
(FxHashSet::default(), FxHashSet::default(), Vec::new())
|
(FxIndexSet::default(), FxIndexSet::default(), Vec::new())
|
||||||
});
|
});
|
||||||
entry.0.insert(cause_span);
|
entry.0.insert(cause_span);
|
||||||
entry.1.insert((ident.span, ""));
|
entry.1.insert((ident.span, ""));
|
||||||
|
@ -840,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
unsatisfied_bounds = true;
|
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.
|
// The requirements that didn't have an `impl` span to show.
|
||||||
let mut bound_list = unsatisfied_predicates
|
let mut bound_list = unsatisfied_predicates
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -889,8 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
|
for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
|
||||||
restrict_type_params = true;
|
restrict_type_params = true;
|
||||||
// #74886: Sort here so that the output is always the same.
|
// #74886: Sort here so that the output is always the same.
|
||||||
let mut obligations = obligations.into_iter().collect::<Vec<_>>();
|
let obligations = obligations.to_sorted_stable_ord();
|
||||||
obligations.sort();
|
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
format!(
|
format!(
|
||||||
|
@ -2053,7 +2055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ty::Adt(def, _) => Some(def.did()),
|
ty::Adt(def, _) => Some(def.did()),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<FxHashSet<_>>();
|
.collect::<FxIndexSet<_>>();
|
||||||
let mut spans: MultiSpan = def_ids
|
let mut spans: MultiSpan = def_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|def_id| {
|
.filter_map(|def_id| {
|
||||||
|
@ -2669,7 +2671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Nothing,
|
Nothing,
|
||||||
}
|
}
|
||||||
let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
|
let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
|
||||||
let trait_def_ids: FxHashSet<DefId> = ast_generics
|
let trait_def_ids: DefIdSet = ast_generics
|
||||||
.bounds_for_param(def_id)
|
.bounds_for_param(def_id)
|
||||||
.flat_map(|bp| bp.bounds.iter())
|
.flat_map(|bp| bp.bounds.iter())
|
||||||
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
|
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
|
|
||||||
use crate::expr_use_visitor as euv;
|
use crate::expr_use_visitor as euv;
|
||||||
|
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
|
||||||
use rustc_errors::{Applicability, MultiSpan};
|
use rustc_errors::{Applicability, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
@ -48,7 +49,7 @@ use rustc_span::sym;
|
||||||
use rustc_span::{BytePos, Pos, Span, Symbol};
|
use rustc_span::{BytePos, Pos, Span, Symbol};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
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 rustc_target::abi::FIRST_VARIANT;
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -910,19 +911,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// Combines all the reasons for 2229 migrations
|
/// Combines all the reasons for 2229 migrations
|
||||||
fn compute_2229_migrations_reasons(
|
fn compute_2229_migrations_reasons(
|
||||||
&self,
|
&self,
|
||||||
auto_trait_reasons: FxHashSet<&'static str>,
|
auto_trait_reasons: UnordSet<&'static str>,
|
||||||
drop_order: bool,
|
drop_order: bool,
|
||||||
) -> MigrationWarningReason {
|
) -> MigrationWarningReason {
|
||||||
let mut reasons = MigrationWarningReason::default();
|
MigrationWarningReason {
|
||||||
|
auto_traits: auto_trait_reasons.to_sorted_stable_ord(),
|
||||||
reasons.auto_traits.extend(auto_trait_reasons);
|
drop_order,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Figures out the list of root variables (and their types) that aren't completely
|
/// 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>>,
|
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
|
||||||
var_hir_id: hir::HirId,
|
var_hir_id: hir::HirId,
|
||||||
closure_clause: hir::CaptureBy,
|
closure_clause: hir::CaptureBy,
|
||||||
) -> Option<FxHashMap<UpvarMigrationInfo, FxHashSet<&'static str>>> {
|
) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>> {
|
||||||
let auto_traits_def_id = vec![
|
let auto_traits_def_id = vec![
|
||||||
self.tcx.lang_items().clone_trait(),
|
self.tcx.lang_items().clone_trait(),
|
||||||
self.tcx.lang_items().sync_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
|
// Check whether captured fields also implement the trait
|
||||||
for capture in root_var_min_capture_list.iter() {
|
for capture in root_var_min_capture_list.iter() {
|
||||||
let ty = apply_capture_kind_on_capture_ty(
|
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
|
// Checks if for any of the auto traits, one or more trait is implemented
|
||||||
// by the root variable but not by the capture
|
// 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>>,
|
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
|
||||||
closure_clause: hir::CaptureBy,
|
closure_clause: hir::CaptureBy,
|
||||||
var_hir_id: hir::HirId,
|
var_hir_id: hir::HirId,
|
||||||
) -> Option<FxHashSet<UpvarMigrationInfo>> {
|
) -> Option<FxIndexSet<UpvarMigrationInfo>> {
|
||||||
let ty = self.resolve_vars_if_possible(self.node_ty(var_hir_id));
|
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)) {
|
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 {
|
match closure_clause {
|
||||||
// Only migrate if closure is a move closure
|
// Only migrate if closure is a move closure
|
||||||
hir::CaptureBy::Value => {
|
hir::CaptureBy::Value => {
|
||||||
let mut diagnostics_info = FxHashSet::default();
|
let mut diagnostics_info = FxIndexSet::default();
|
||||||
let upvars =
|
let upvars =
|
||||||
self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
|
self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
|
||||||
let upvar = upvars[&var_hir_id];
|
let upvar = upvars[&var_hir_id];
|
||||||
|
@ -1085,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
debug!(?root_var_min_capture_list);
|
debug!(?root_var_min_capture_list);
|
||||||
|
|
||||||
let mut projections_list = Vec::new();
|
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() {
|
for captured_place in root_var_min_capture_list.iter() {
|
||||||
match captured_place.info.capture_kind {
|
match captured_place.info.capture_kind {
|
||||||
|
@ -1155,7 +1150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut need_migrations = Vec::new();
|
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;
|
let mut drop_migration_needed = false;
|
||||||
|
|
||||||
// Perform auto-trait analysis
|
// Perform auto-trait analysis
|
||||||
|
@ -1167,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
diagnostics_info
|
diagnostics_info
|
||||||
} else {
|
} else {
|
||||||
FxHashMap::default()
|
FxIndexMap::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
|
let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
|
||||||
|
@ -1181,7 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
drop_migration_needed = true;
|
drop_migration_needed = true;
|
||||||
diagnostics_info
|
diagnostics_info
|
||||||
} else {
|
} else {
|
||||||
FxHashSet::default()
|
FxIndexSet::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Combine all the captures responsible for needing migrations into one HashSet
|
// 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) {
|
if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) {
|
||||||
reasons.clone()
|
reasons.clone()
|
||||||
} else {
|
} else {
|
||||||
FxHashSet::default()
|
UnordSet::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if migration is needed because of drop reorder as a result of that capture
|
// 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
|
// Combine all the reasons of why the root variable should be captured as a result of
|
||||||
// auto trait implementation issues
|
// 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 {
|
diagnostics_info.push(MigrationLintNote {
|
||||||
captures_info,
|
captures_info,
|
||||||
|
|
|
@ -4,17 +4,15 @@
|
||||||
|
|
||||||
use crate::FnCtxt;
|
use crate::FnCtxt;
|
||||||
use hir::def_id::LocalDefId;
|
use hir::def_id::LocalDefId;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::unord::ExtendUnord;
|
||||||
use rustc_errors::{ErrorGuaranteed, StashKey};
|
use rustc_errors::{ErrorGuaranteed, StashKey};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
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::adjustment::{Adjust, Adjustment, PointerCoercion};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
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::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -376,66 +374,75 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
|
||||||
|
|
||||||
impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
fn eval_closure_size(&mut self) {
|
fn eval_closure_size(&mut self) {
|
||||||
let mut res: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>> = Default::default();
|
self.tcx().with_stable_hashing_context(|ref hcx| {
|
||||||
for (&closure_def_id, data) in self.fcx.typeck_results.borrow().closure_size_eval.iter() {
|
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 closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
|
||||||
|
|
||||||
let data = self.resolve(*data, &closure_hir_id);
|
let data = self.resolve(*data, &closure_hir_id);
|
||||||
|
(closure_def_id, data)
|
||||||
res.insert(closure_def_id, data);
|
})
|
||||||
|
.collect();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.typeck_results.closure_size_eval = res;
|
|
||||||
}
|
|
||||||
fn visit_min_capture_map(&mut self) {
|
fn visit_min_capture_map(&mut self) {
|
||||||
let mut min_captures_wb = ty::MinCaptureInformationMap::with_capacity_and_hasher(
|
self.tcx().with_stable_hashing_context(|ref hcx| {
|
||||||
self.fcx.typeck_results.borrow().closure_min_captures.len(),
|
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||||
Default::default(),
|
|
||||||
);
|
self.typeck_results.closure_min_captures = fcx_typeck_results
|
||||||
for (&closure_def_id, root_min_captures) in
|
.closure_min_captures
|
||||||
self.fcx.typeck_results.borrow().closure_min_captures.iter()
|
.to_sorted(hcx, false)
|
||||||
{
|
.into_iter()
|
||||||
let mut root_var_map_wb = ty::RootVariableMinCaptureList::with_capacity_and_hasher(
|
.map(|(&closure_def_id, root_min_captures)| {
|
||||||
root_min_captures.len(),
|
let root_var_map_wb = root_min_captures
|
||||||
Default::default(),
|
.iter()
|
||||||
);
|
.map(|(var_hir_id, min_list)| {
|
||||||
for (var_hir_id, min_list) in root_min_captures.iter() {
|
|
||||||
let min_list_wb = min_list
|
let min_list_wb = min_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(|captured_place| {
|
.map(|captured_place| {
|
||||||
let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| {
|
let locatable =
|
||||||
|
captured_place.info.path_expr_id.unwrap_or_else(|| {
|
||||||
self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
|
self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.resolve(captured_place.clone(), &locatable)
|
self.resolve(captured_place.clone(), &locatable)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
root_var_map_wb.insert(*var_hir_id, min_list_wb);
|
(*var_hir_id, min_list_wb)
|
||||||
}
|
})
|
||||||
min_captures_wb.insert(closure_def_id, root_var_map_wb);
|
.collect();
|
||||||
}
|
(closure_def_id, root_var_map_wb)
|
||||||
|
})
|
||||||
self.typeck_results.closure_min_captures = min_captures_wb;
|
.collect();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fake_reads_map(&mut self) {
|
fn visit_fake_reads_map(&mut self) {
|
||||||
let mut resolved_closure_fake_reads: FxHashMap<
|
self.tcx().with_stable_hashing_context(move |ref hcx| {
|
||||||
LocalDefId,
|
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||||
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);
|
|
||||||
|
|
||||||
|
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);
|
let resolved_fake_read = self.resolve(place.clone(), &locatable);
|
||||||
resolved_fake_reads.push((resolved_fake_read, *cause, *hir_id));
|
(resolved_fake_read, *cause, *hir_id)
|
||||||
}
|
})
|
||||||
resolved_closure_fake_reads.insert(closure_def_id, resolved_fake_reads);
|
.collect();
|
||||||
}
|
|
||||||
self.typeck_results.closure_fake_reads = resolved_closure_fake_reads;
|
(closure_def_id, resolved_fake_reads)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_closures(&mut self) {
|
fn visit_closures(&mut self) {
|
||||||
|
@ -520,7 +527,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
let fcx_typeck_results = self.fcx.typeck_results.borrow();
|
||||||
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
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)| {
|
fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
|
||||||
if cfg!(debug_assertions) && c_sig.has_infer() {
|
if cfg!(debug_assertions) && c_sig.has_infer() {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
|
@ -540,10 +547,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
|
||||||
self.typeck_results.generator_interior_types =
|
self.typeck_results.generator_interior_types =
|
||||||
fcx_typeck_results.generator_interior_types.clone();
|
fcx_typeck_results.generator_interior_types.clone();
|
||||||
for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.iter() {
|
self.tcx().with_stable_hashing_context(move |ref hcx| {
|
||||||
let predicates = self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
|
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);
|
self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::ty::TyCtxt;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::{HirIdMap, Node};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
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
|
/// and not the enclosing *statement*. Expressions that are not present in this
|
||||||
/// table are not rvalue candidates. The set of rvalue candidates is computed
|
/// table are not rvalue candidates. The set of rvalue candidates is computed
|
||||||
/// during type check based on a traversal of the AST.
|
/// during type check based on a traversal of the AST.
|
||||||
pub rvalue_candidates: FxHashMap<hir::HirId, RvalueCandidateType>,
|
pub rvalue_candidates: HirIdMap<RvalueCandidateType>,
|
||||||
|
|
||||||
/// If there are any `yield` nested within a scope, this map
|
/// If there are any `yield` nested within a scope, this map
|
||||||
/// stores the `Span` of the last one and its index in the
|
/// stores the `Span` of the last one and its index in the
|
||||||
|
|
|
@ -6,9 +6,10 @@ use crate::{mir, ty};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::query::Providers;
|
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::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::{self as hir, LangItem};
|
use rustc_hir::{self as hir, LangItem};
|
||||||
|
use rustc_span::def_id::LocalDefIdMap;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
|
@ -56,12 +57,9 @@ pub enum UpvarCapture {
|
||||||
ByRef(BorrowKind),
|
ByRef(BorrowKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
|
|
||||||
pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>;
|
|
||||||
|
|
||||||
/// Given the closure DefId this map provides a map of root variables to minimum
|
/// 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.
|
/// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
|
||||||
pub type MinCaptureInformationMap<'tcx> = FxHashMap<LocalDefId, RootVariableMinCaptureList<'tcx>>;
|
pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap<RootVariableMinCaptureList<'tcx>>;
|
||||||
|
|
||||||
/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.
|
/// 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
|
/// Used to track the minimum set of `Place`s that need to be captured to support all
|
||||||
|
|
|
@ -82,8 +82,7 @@ pub use self::binding::BindingMode::*;
|
||||||
pub use self::closure::{
|
pub use self::closure::{
|
||||||
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
|
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
|
||||||
CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
|
CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
|
||||||
RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
|
RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
|
||||||
CAPTURE_STRUCT_LOCAL,
|
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::middle::region::{Scope, ScopeData, ScopeTree};
|
use crate::middle::region::{Scope, ScopeData, ScopeTree};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::ItemLocalMap;
|
||||||
|
|
||||||
/// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
|
/// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
|
||||||
/// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
|
/// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
|
||||||
#[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
|
#[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
|
||||||
pub struct RvalueScopes {
|
pub struct RvalueScopes {
|
||||||
map: FxHashMap<hir::ItemLocalId, Option<Scope>>,
|
map: ItemLocalMap<Option<Scope>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RvalueScopes {
|
impl RvalueScopes {
|
||||||
|
|
|
@ -7,8 +7,10 @@ use crate::{
|
||||||
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
|
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
use rustc_data_structures::{
|
||||||
use rustc_data_structures::unord::{UnordItems, UnordSet};
|
fx::FxIndexMap,
|
||||||
|
unord::{ExtendUnord, UnordItems, UnordSet},
|
||||||
|
};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_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
|
/// 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
|
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||||
/// issue by fake reading `t`.
|
/// issue by fake reading `t`.
|
||||||
pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||||
|
|
||||||
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
|
||||||
/// by applying extended parameter rules.
|
/// by applying extended parameter rules.
|
||||||
|
@ -194,7 +196,7 @@ pub struct TypeckResults<'tcx> {
|
||||||
/// Stores the predicates that apply on generator witness types.
|
/// Stores the predicates that apply on generator witness types.
|
||||||
/// formatting modified file tests/ui/generator/retain-resume-ref.rs
|
/// formatting modified file tests/ui/generator/retain-resume-ref.rs
|
||||||
pub generator_interior_predicates:
|
pub generator_interior_predicates:
|
||||||
FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
|
LocalDefIdMap<Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
|
||||||
|
|
||||||
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
|
||||||
/// as `&[u8]`, depending on the pattern in which they are used.
|
/// 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`
|
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
|
||||||
/// on closure size.
|
/// on closure size.
|
||||||
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
|
pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
|
||||||
|
|
||||||
/// Container types and field indices of `offset_of!` expressions
|
/// Container types and field indices of `offset_of!` expressions
|
||||||
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
|
offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
|
||||||
|
@ -633,7 +635,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
|
||||||
&mut self,
|
&mut self,
|
||||||
items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
|
items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
|
||||||
) {
|
) {
|
||||||
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);
|
validate_hir_id_for_typeck_results(self.hir_owner, id);
|
||||||
(id.local_id, value)
|
(id.local_id, value)
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -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 as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue