1
Fork 0

Auto merge of #108312 - michaelwoerister:hash-set-not-hash-stable, r=eholk

Do not implement HashStable for HashSet (MCP 533)

This PR removes all occurrences of `HashSet` in query results, replacing it either with `FxIndexSet` or with `UnordSet`, and then removes the `HashStable` implementation of `HashSet`. This is part of implementing [MCP 533](https://github.com/rust-lang/compiler-team/issues/533), that is, removing the `HashStable` implementations of all collection types with unstable iteration order.

The changes are mostly mechanical. The only place where additional sorting is happening is in Miri's override implementation of the `exported_symbols` query.
This commit is contained in:
bors 2023-03-08 06:07:11 +00:00
commit 9b60e6c68f
23 changed files with 127 additions and 103 deletions

View file

@ -58,7 +58,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
let mut reachable_non_generics: DefIdMap<_> = tcx let mut reachable_non_generics: DefIdMap<_> = tcx
.reachable_set(()) .reachable_set(())
.iter() .items()
.filter_map(|&def_id| { .filter_map(|&def_id| {
// We want to ignore some FFI functions that are not exposed from // We want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two // this crate. Reachable FFI functions can be lumped into two
@ -136,7 +136,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
}; };
(def_id.to_def_id(), info) (def_id.to_def_id(), info)
}) })
.collect(); .into();
if let Some(id) = tcx.proc_macro_decls_static(()) { if let Some(id) = tcx.proc_macro_decls_static(()) {
reachable_non_generics.insert( reachable_non_generics.insert(

View file

@ -1,7 +1,7 @@
use rustc_ast::ast; use rustc_ast::ast;
use rustc_attr::InstructionSetAttr; use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -418,7 +418,7 @@ pub fn from_target_feature(
/// Computes the set of target features used in a function for the purposes of /// Computes the set of target features used in a function for the purposes of
/// inline assembly. /// inline assembly.
fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxHashSet<Symbol> { fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
let mut target_features = tcx.sess.unstable_target_features.clone(); let mut target_features = tcx.sess.unstable_target_features.clone();
if tcx.def_kind(did).has_codegen_attrs() { if tcx.def_kind(did).has_codegen_attrs() {
let attrs = tcx.codegen_fn_attrs(did); let attrs = tcx.codegen_fn_attrs(did);

View file

@ -617,18 +617,10 @@ where
} }
} }
impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R> // It is not safe to implement HashStable for HashSet or any other collection type
where // with unstable but observable iteration order.
K: ToStableHashKey<HCX> + Eq, // See https://github.com/rust-lang/compiler-team/issues/533 for further information.
R: BuildHasher, impl<V, HCX> !HashStable<HCX> for std::collections::HashSet<V> {}
{
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
let key = key.to_stable_hash_key(hcx);
key.hash_stable(hcx, hasher);
});
}
}
impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V> impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
where where

View file

@ -109,6 +109,12 @@ impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
} }
} }
impl<T> UnordItems<T, std::iter::Empty<T>> {
pub fn empty() -> Self {
UnordItems(std::iter::empty())
}
}
impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> { impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
#[inline] #[inline]
pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> { pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> {
@ -133,6 +139,20 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
items items
} }
#[inline]
pub fn into_sorted_stable_ord(self, use_stable_sort: bool) -> Vec<T>
where
T: Ord + StableOrd,
{
let mut items: Vec<T> = self.0.collect();
if use_stable_sort {
items.sort();
} else {
items.sort_unstable()
}
items
}
pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]> pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]>
where where
T: ToStableHashKey<HCX>, T: ToStableHashKey<HCX>,
@ -175,6 +195,11 @@ impl<V: Eq + Hash> UnordSet<V> {
self.inner.len() self.inner.len()
} }
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline] #[inline]
pub fn insert(&mut self, v: V) -> bool { pub fn insert(&mut self, v: V) -> bool {
self.inner.insert(v) self.inner.insert(v)
@ -253,7 +278,7 @@ impl<V: Eq + Hash> UnordSet<V> {
// We can safely extend this UnordSet from a set of unordered values because that // We can safely extend this UnordSet from a set of unordered values because that
// won't expose the internal ordering anywhere. // won't expose the internal ordering anywhere.
#[inline] #[inline]
pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) { pub fn extend_unord<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
self.inner.extend(items.0) self.inner.extend(items.0)
} }
@ -277,6 +302,12 @@ impl<V: Hash + Eq> FromIterator<V> for UnordSet<V> {
} }
} }
impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
fn from(value: FxHashSet<V>) -> Self {
UnordSet { inner: value }
}
}
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) {

View file

@ -1,5 +1,5 @@
use rustc_ast::InlineAsmTemplatePiece; use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint; use rustc_session::lint;
@ -51,7 +51,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
template: &[InlineAsmTemplatePiece], template: &[InlineAsmTemplatePiece],
is_input: bool, is_input: bool,
tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>, tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
) -> Option<InlineAsmType> { ) -> Option<InlineAsmType> {
let ty = (self.get_operand_ty)(expr); let ty = (self.get_operand_ty)(expr);
if ty.has_non_region_infer() { if ty.has_non_region_infer() {
@ -201,7 +201,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// (!). In that case we still need the earlier check to verify that the // (!). In that case we still need the earlier check to verify that the
// register class is usable at all. // register class is usable at all.
if let Some(feature) = feature { if let Some(feature) = feature {
if !target_features.contains(&feature) { if !target_features.contains(feature) {
let msg = &format!("`{}` target feature is not enabled", feature); let msg = &format!("`{}` target feature is not enabled", feature);
let mut err = self.tcx.sess.struct_span_err(expr.span, msg); let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(&format!( err.note(&format!(

View file

@ -10,7 +10,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
for item_def_id in tcx.hir().body_owners() { for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id); let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend(imports.items().copied()); used_trait_imports.extend_unord(imports.items().copied());
} }
for &id in tcx.maybe_unused_trait_imports(()) { for &id in tcx.maybe_unused_trait_imports(()) {

View file

@ -94,7 +94,8 @@ macro_rules! arena_types {
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>, [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[decode] attribute: rustc_ast::Attribute, [decode] attribute: rustc_ast::Attribute,
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, [] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
[] hir_id_set: rustc_hir::HirIdSet, [] hir_id_set: rustc_hir::HirIdSet,
// Interned types // Interned types

View file

@ -2,7 +2,7 @@
use crate::mir::{Body, ConstantKind, Promoted}; use crate::mir::{Body, ConstantKind, Promoted};
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet;
use rustc_data_structures::vec_map::VecMap; use rustc_data_structures::vec_map::VecMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
@ -123,7 +123,7 @@ pub struct UnsafetyCheckResult {
pub violations: Vec<UnsafetyViolation>, pub violations: Vec<UnsafetyViolation>,
/// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
pub used_unsafe_blocks: FxHashSet<hir::HirId>, pub used_unsafe_blocks: UnordSet<hir::HirId>,
/// This is `Some` iff the item is not a closure. /// This is `Some` iff the item is not a closure.
pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>, pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,

View file

@ -764,7 +764,7 @@ rustc_queries! {
/// ///
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
///`{ trait_f: impl_f, trait_g: impl_g }` ///`{ trait_f: impl_f, trait_g: impl_g }`
query impl_item_implementor_ids(impl_id: DefId) -> &'tcx FxHashMap<DefId, DefId> { query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap<DefId> {
arena_cache arena_cache
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
} }
@ -906,8 +906,8 @@ rustc_queries! {
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and
/// their respective impl (i.e., part of the derive macro) /// their respective impl (i.e., part of the derive macro)
query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx ( query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx (
FxHashSet<LocalDefId>, LocalDefIdSet,
FxHashMap<LocalDefId, Vec<(DefId, DefId)>> LocalDefIdMap<Vec<(DefId, DefId)>>
) { ) {
arena_cache arena_cache
desc { "finding live symbols in crate" } desc { "finding live symbols in crate" }
@ -1120,7 +1120,7 @@ rustc_queries! {
desc { "checking for private elements in public interfaces" } desc { "checking for private elements in public interfaces" }
} }
query reachable_set(_: ()) -> &'tcx FxHashSet<LocalDefId> { query reachable_set(_: ()) -> &'tcx LocalDefIdSet {
arena_cache arena_cache
desc { "reachability" } desc { "reachability" }
} }
@ -1229,7 +1229,7 @@ rustc_queries! {
separate_provide_extern separate_provide_extern
} }
query asm_target_features(def_id: DefId) -> &'tcx FxHashSet<Symbol> { query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
} }
@ -1845,7 +1845,7 @@ rustc_queries! {
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> { query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { "fetching potentially unused trait imports" } desc { "fetching potentially unused trait imports" }
} }
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> { query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx UnordSet<Symbol> {
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) } desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
} }

View file

@ -36,6 +36,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal}; use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{ use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
}; };
@ -2486,7 +2487,9 @@ pub fn provide(providers: &mut ty::query::Providers) {
providers.maybe_unused_trait_imports = providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.names_imported_by_glob_use = |tcx, id| { providers.names_imported_by_glob_use = |tcx, id| {
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default()) tcx.arena.alloc(UnordSet::from(
tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default(),
))
}; };
providers.extern_mod_stmt_cnum = providers.extern_mod_stmt_cnum =

View file

@ -41,7 +41,7 @@ use rustc_arena::TypedArena;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal; use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -50,7 +50,9 @@ use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, DocLinkResMap}; use rustc_hir::def::{DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::def_id::{
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
};
use rustc_hir::hir_id::OwnerId; use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate};

View file

@ -1,4 +1,4 @@
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::{UnordItems, UnordSet};
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
@ -24,7 +24,7 @@ pub struct UnsafetyChecker<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
/// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
used_unsafe_blocks: FxHashSet<HirId>, used_unsafe_blocks: UnordSet<HirId>,
} }
impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
@ -129,7 +129,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
let def_id = def_id.expect_local(); let def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(def_id); self.tcx.unsafety_check_result(def_id);
self.register_violations(violations, used_unsafe_blocks.iter().copied()); self.register_violations(violations, used_unsafe_blocks.items().copied());
} }
}, },
_ => {} _ => {}
@ -151,7 +151,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
let local_def_id = def_id.expect_local(); let local_def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(local_def_id); self.tcx.unsafety_check_result(local_def_id);
self.register_violations(violations, used_unsafe_blocks.iter().copied()); self.register_violations(violations, used_unsafe_blocks.items().copied());
} }
} }
} }
@ -268,14 +268,14 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
.lint_root; .lint_root;
self.register_violations( self.register_violations(
[&UnsafetyViolation { source_info, lint_root, kind, details }], [&UnsafetyViolation { source_info, lint_root, kind, details }],
[], UnordItems::empty(),
); );
} }
fn register_violations<'a>( fn register_violations<'a>(
&mut self, &mut self,
violations: impl IntoIterator<Item = &'a UnsafetyViolation>, violations: impl IntoIterator<Item = &'a UnsafetyViolation>,
new_used_unsafe_blocks: impl IntoIterator<Item = HirId>, new_used_unsafe_blocks: UnordItems<HirId, impl Iterator<Item = HirId>>,
) { ) {
let safety = self.body.source_scopes[self.source_info.scope] let safety = self.body.source_scopes[self.source_info.scope]
.local_data .local_data
@ -308,9 +308,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
}), }),
}; };
new_used_unsafe_blocks.into_iter().for_each(|hir_id| { self.used_unsafe_blocks.extend_unord(new_used_unsafe_blocks);
self.used_unsafe_blocks.insert(hir_id);
});
} }
fn check_mut_borrowing_layout_constrained_field( fn check_mut_borrowing_layout_constrained_field(
&mut self, &mut self,
@ -407,7 +405,7 @@ enum Context {
struct UnusedUnsafeVisitor<'a, 'tcx> { struct UnusedUnsafeVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
used_unsafe_blocks: &'a FxHashSet<HirId>, used_unsafe_blocks: &'a UnordSet<HirId>,
context: Context, context: Context,
unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>, unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>,
} }
@ -458,7 +456,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
fn check_unused_unsafe( fn check_unused_unsafe(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
def_id: LocalDefId, def_id: LocalDefId,
used_unsafe_blocks: &FxHashSet<HirId>, used_unsafe_blocks: &UnordSet<HirId>,
) -> Vec<(HirId, UnusedUnsafe)> { ) -> Vec<(HirId, UnusedUnsafe)> {
let body_id = tcx.hir().maybe_body_owned_by(def_id); let body_id = tcx.hir().maybe_body_owned_by(def_id);
@ -505,7 +503,7 @@ fn unsafety_check_result(
if body.is_custom_mir() { if body.is_custom_mir() {
return tcx.arena.alloc(UnsafetyCheckResult { return tcx.arena.alloc(UnsafetyCheckResult {
violations: Vec::new(), violations: Vec::new(),
used_unsafe_blocks: FxHashSet::default(), used_unsafe_blocks: Default::default(),
unused_unsafes: Some(Vec::new()), unused_unsafes: Some(Vec::new()),
}); });
} }

View file

@ -2,8 +2,8 @@
// closely. The idea is that all reachable symbols are live, codes called // closely. The idea is that all reachable symbols are live, codes called
// from live codes are live, and everything else is dead. // from live codes are live, and everything else is dead.
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
use itertools::Itertools; use itertools::Itertools;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
@ -45,17 +45,17 @@ struct MarkSymbolVisitor<'tcx> {
worklist: Vec<LocalDefId>, worklist: Vec<LocalDefId>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
live_symbols: FxHashSet<LocalDefId>, live_symbols: LocalDefIdSet,
repr_has_repr_c: bool, repr_has_repr_c: bool,
repr_has_repr_simd: bool, repr_has_repr_simd: bool,
in_pat: bool, in_pat: bool,
ignore_variant_stack: Vec<DefId>, ignore_variant_stack: Vec<DefId>,
// maps from tuple struct constructors to tuple struct items // maps from tuple struct constructors to tuple struct items
struct_constructors: FxHashMap<LocalDefId, LocalDefId>, struct_constructors: LocalDefIdMap<LocalDefId>,
// maps from ADTs to ignored derived traits (e.g. Debug and Clone) // maps from ADTs to ignored derived traits (e.g. Debug and Clone)
// and the span of their respective impl (i.e., part of the derive // and the span of their respective impl (i.e., part of the derive
// macro) // macro)
ignored_derived_traits: FxHashMap<LocalDefId, Vec<(DefId, DefId)>>, ignored_derived_traits: LocalDefIdMap<Vec<(DefId, DefId)>>,
} }
impl<'tcx> MarkSymbolVisitor<'tcx> { impl<'tcx> MarkSymbolVisitor<'tcx> {
@ -237,7 +237,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
} }
fn mark_live_symbols(&mut self) { fn mark_live_symbols(&mut self) {
let mut scanned = FxHashSet::default(); let mut scanned = LocalDefIdSet::default();
while let Some(id) = self.worklist.pop() { while let Some(id) = self.worklist.pop() {
if !scanned.insert(id) { if !scanned.insert(id) {
continue; continue;
@ -506,7 +506,7 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool
fn check_item<'tcx>( fn check_item<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
worklist: &mut Vec<LocalDefId>, worklist: &mut Vec<LocalDefId>,
struct_constructors: &mut FxHashMap<LocalDefId, LocalDefId>, struct_constructors: &mut LocalDefIdMap<LocalDefId>,
id: hir::ItemId, id: hir::ItemId,
) { ) {
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id); let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
@ -583,9 +583,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::
} }
} }
fn create_and_seed_worklist( fn create_and_seed_worklist(tcx: TyCtxt<'_>) -> (Vec<LocalDefId>, LocalDefIdMap<LocalDefId>) {
tcx: TyCtxt<'_>,
) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) {
let effective_visibilities = &tcx.effective_visibilities(()); let effective_visibilities = &tcx.effective_visibilities(());
// see `MarkSymbolVisitor::struct_constructors` // see `MarkSymbolVisitor::struct_constructors`
let mut struct_constructors = Default::default(); let mut struct_constructors = Default::default();
@ -617,7 +615,7 @@ fn create_and_seed_worklist(
fn live_symbols_and_ignored_derived_traits( fn live_symbols_and_ignored_derived_traits(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
(): (), (): (),
) -> (FxHashSet<LocalDefId>, FxHashMap<LocalDefId, Vec<(DefId, DefId)>>) { ) -> (LocalDefIdSet, LocalDefIdMap<Vec<(DefId, DefId)>>) {
let (worklist, struct_constructors) = create_and_seed_worklist(tcx); let (worklist, struct_constructors) = create_and_seed_worklist(tcx);
let mut symbol_visitor = MarkSymbolVisitor { let mut symbol_visitor = MarkSymbolVisitor {
worklist, worklist,
@ -629,7 +627,7 @@ fn live_symbols_and_ignored_derived_traits(
in_pat: false, in_pat: false,
ignore_variant_stack: vec![], ignore_variant_stack: vec![],
struct_constructors, struct_constructors,
ignored_derived_traits: FxHashMap::default(), ignored_derived_traits: Default::default(),
}; };
symbol_visitor.mark_live_symbols(); symbol_visitor.mark_live_symbols();
(symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits) (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
@ -643,8 +641,8 @@ struct DeadVariant {
struct DeadVisitor<'tcx> { struct DeadVisitor<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
live_symbols: &'tcx FxHashSet<LocalDefId>, live_symbols: &'tcx LocalDefIdSet,
ignored_derived_traits: &'tcx FxHashMap<LocalDefId, Vec<(DefId, DefId)>>, ignored_derived_traits: &'tcx LocalDefIdMap<Vec<(DefId, DefId)>>,
} }
enum ShouldWarnAboutField { enum ShouldWarnAboutField {

View file

@ -5,7 +5,7 @@
// makes all other generics or inline functions that it references // makes all other generics or inline functions that it references
// reachable as well. // reachable as well.
use rustc_data_structures::fx::FxHashSet; use hir::def_id::LocalDefIdSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
@ -63,7 +63,7 @@ struct ReachableContext<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
// The set of items which must be exported in the linkage sense. // The set of items which must be exported in the linkage sense.
reachable_symbols: FxHashSet<LocalDefId>, reachable_symbols: LocalDefIdSet,
// A worklist of item IDs. Each item ID in this worklist will be inlined // A worklist of item IDs. Each item ID in this worklist will be inlined
// and will be scanned for further references. // and will be scanned for further references.
// FIXME(eddyb) benchmark if this would be faster as a `VecDeque`. // FIXME(eddyb) benchmark if this would be faster as a `VecDeque`.
@ -175,7 +175,7 @@ impl<'tcx> ReachableContext<'tcx> {
// Step 2: Mark all symbols that the symbols on the worklist touch. // Step 2: Mark all symbols that the symbols on the worklist touch.
fn propagate(&mut self) { fn propagate(&mut self) {
let mut scanned = FxHashSet::default(); let mut scanned = LocalDefIdSet::default();
while let Some(search_item) = self.worklist.pop() { while let Some(search_item) = self.worklist.pop() {
if !scanned.insert(search_item) { if !scanned.insert(search_item) {
continue; continue;
@ -361,7 +361,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
} }
fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> { fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
let effective_visibilities = &tcx.effective_visibilities(()); let effective_visibilities = &tcx.effective_visibilities(());
let any_library = let any_library =

View file

@ -11,7 +11,7 @@ use crate::{filesearch, lint};
pub use rustc_ast::attr::MarkedAttrs; pub use rustc_ast::attr::MarkedAttrs;
pub use rustc_ast::Attribute; pub use rustc_ast::Attribute;
use rustc_data_structures::flock; use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::jobserver::{self, Client};
use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef};
use rustc_data_structures::sync::{ use rustc_data_structures::sync::{
@ -207,10 +207,10 @@ pub struct Session {
pub asm_arch: Option<InlineAsmArch>, pub asm_arch: Option<InlineAsmArch>,
/// Set of enabled features for the current target. /// Set of enabled features for the current target.
pub target_features: FxHashSet<Symbol>, pub target_features: FxIndexSet<Symbol>,
/// Set of enabled features for the current target, including unstable ones. /// Set of enabled features for the current target, including unstable ones.
pub unstable_target_features: FxHashSet<Symbol>, pub unstable_target_features: FxIndexSet<Symbol>,
} }
pub struct PerfStats { pub struct PerfStats {
@ -1488,8 +1488,8 @@ pub fn build_session(
ctfe_backtrace, ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()), miri_unleashed_features: Lock::new(Default::default()),
asm_arch, asm_arch,
target_features: FxHashSet::default(), target_features: Default::default(),
unstable_target_features: FxHashSet::default(), unstable_target_features: Default::default(),
}; };
validate_commandline_args_with_session_available(&sess); validate_commandline_args_with_session_available(&sess);

View file

@ -1,6 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::{RelocModel, Target}; use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol; use rustc_span::Symbol;
use std::fmt; use std::fmt;
@ -80,7 +80,7 @@ pub fn target_reserves_x18(target: &Target) -> bool {
fn reserved_x18( fn reserved_x18(
_arch: InlineAsmArch, _arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>, _target_features: &FxIndexSet<Symbol>,
target: &Target, target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {

View file

@ -1,6 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::{RelocModel, Target}; use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol}; use rustc_span::{sym, Symbol};
use std::fmt; use std::fmt;
@ -64,14 +64,14 @@ impl ArmInlineAsmRegClass {
} }
// This uses the same logic as useR7AsFramePointer in LLVM // This uses the same logic as useR7AsFramePointer in LLVM
fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) -> bool { fn frame_pointer_is_r7(target_features: &FxIndexSet<Symbol>, target: &Target) -> bool {
target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode))
} }
fn frame_pointer_r11( fn frame_pointer_r11(
arch: InlineAsmArch, arch: InlineAsmArch,
reloc_model: RelocModel, reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
target: &Target, target: &Target,
is_clobber: bool, is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -87,7 +87,7 @@ fn frame_pointer_r11(
fn frame_pointer_r7( fn frame_pointer_r7(
_arch: InlineAsmArch, _arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
target: &Target, target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -101,7 +101,7 @@ fn frame_pointer_r7(
fn not_thumb1( fn not_thumb1(
_arch: InlineAsmArch, _arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
is_clobber: bool, is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -118,7 +118,7 @@ fn not_thumb1(
fn reserved_r9( fn reserved_r9(
arch: InlineAsmArch, arch: InlineAsmArch,
reloc_model: RelocModel, reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
target: &Target, target: &Target,
is_clobber: bool, is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {

View file

@ -1,6 +1,6 @@
use crate::spec::Target; use crate::spec::Target;
use crate::{abi::Size, spec::RelocModel}; use crate::{abi::Size, spec::RelocModel};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol; use rustc_span::Symbol;
use std::fmt; use std::fmt;
@ -37,13 +37,14 @@ macro_rules! def_reg_class {
pub(super) fn regclass_map() -> rustc_data_structures::fx::FxHashMap< pub(super) fn regclass_map() -> rustc_data_structures::fx::FxHashMap<
super::InlineAsmRegClass, super::InlineAsmRegClass,
rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>, rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>,
> { > {
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxIndexSet;
use super::InlineAsmRegClass; use super::InlineAsmRegClass;
let mut map = FxHashMap::default(); let mut map = FxHashMap::default();
$( $(
map.insert(InlineAsmRegClass::$arch($arch_regclass::$class), FxHashSet::default()); map.insert(InlineAsmRegClass::$arch($arch_regclass::$class), FxIndexSet::default());
)* )*
map map
} }
@ -94,7 +95,7 @@ macro_rules! def_regs {
pub fn validate(self, pub fn validate(self,
_arch: super::InlineAsmArch, _arch: super::InlineAsmArch,
_reloc_model: crate::spec::RelocModel, _reloc_model: crate::spec::RelocModel,
_target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
_target: &crate::spec::Target, _target: &crate::spec::Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -118,11 +119,11 @@ macro_rules! def_regs {
pub(super) fn fill_reg_map( pub(super) fn fill_reg_map(
_arch: super::InlineAsmArch, _arch: super::InlineAsmArch,
_reloc_model: crate::spec::RelocModel, _reloc_model: crate::spec::RelocModel,
_target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
_target: &crate::spec::Target, _target: &crate::spec::Target,
_map: &mut rustc_data_structures::fx::FxHashMap< _map: &mut rustc_data_structures::fx::FxHashMap<
super::InlineAsmRegClass, super::InlineAsmRegClass,
rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>, rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>,
>, >,
) { ) {
#[allow(unused_imports)] #[allow(unused_imports)]
@ -334,7 +335,7 @@ impl InlineAsmReg {
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
reloc_model: RelocModel, reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
target: &Target, target: &Target,
is_clobber: bool, is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -701,9 +702,9 @@ impl fmt::Display for InlineAsmType {
pub fn allocatable_registers( pub fn allocatable_registers(
arch: InlineAsmArch, arch: InlineAsmArch,
reloc_model: RelocModel, reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
target: &crate::spec::Target, target: &crate::spec::Target,
) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> { ) -> FxHashMap<InlineAsmRegClass, FxIndexSet<InlineAsmReg>> {
match arch { match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => { InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
let mut map = x86::regclass_map(); let mut map = x86::regclass_map();

View file

@ -1,6 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::{RelocModel, Target}; use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol}; use rustc_span::{sym, Symbol};
use std::fmt; use std::fmt;
@ -55,7 +55,7 @@ impl RiscVInlineAsmRegClass {
fn not_e( fn not_e(
_arch: InlineAsmArch, _arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>, target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {

View file

@ -1,6 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::{RelocModel, Target}; use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol; use rustc_span::Symbol;
use std::fmt; use std::fmt;
@ -147,7 +147,7 @@ impl X86InlineAsmRegClass {
fn x86_64_only( fn x86_64_only(
arch: InlineAsmArch, arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>, _target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -161,7 +161,7 @@ fn x86_64_only(
fn high_byte( fn high_byte(
arch: InlineAsmArch, arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>, _target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -174,7 +174,7 @@ fn high_byte(
fn rbx_reserved( fn rbx_reserved(
arch: InlineAsmArch, arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>, _target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
@ -190,7 +190,7 @@ fn rbx_reserved(
fn esi_reserved( fn esi_reserved(
arch: InlineAsmArch, arch: InlineAsmArch,
_reloc_model: RelocModel, _reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>, _target_features: &FxIndexSet<Symbol>,
_target: &Target, _target: &Target,
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {

View file

@ -1,7 +1,6 @@
use rustc_data_structures::fx::FxHashMap;
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, DefIdMap, LocalDefId};
use rustc_hir::definitions::DefPathData; use rustc_hir::definitions::DefPathData;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt}; use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
@ -97,7 +96,7 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
} }
} }
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> { fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
tcx.associated_items(impl_id) tcx.associated_items(impl_id)
.in_definition_order() .in_definition_order()
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id))) .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))

View file

@ -155,14 +155,10 @@ impl LateLintPass<'_> for WildcardImports {
) )
}; };
let imports_string = if used_imports.len() == 1 { let mut imports = used_imports.items().map(ToString::to_string).into_sorted_stable_ord(false);
used_imports.iter().next().unwrap().to_string() let imports_string = if imports.len() == 1 {
imports.pop().unwrap()
} else { } else {
let mut imports = used_imports
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>();
imports.sort();
if braced_glob { if braced_glob {
imports.join(", ") imports.join(", ")
} else { } else {

View file

@ -109,11 +109,14 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
// an empty result if `tcx.sess.opts.output_types.should_codegen()` is false. // an empty result if `tcx.sess.opts.output_types.should_codegen()` is false.
local_providers.exported_symbols = |tcx, cnum| { local_providers.exported_symbols = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE); assert_eq!(cnum, LOCAL_CRATE);
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
tcx.reachable_set(()).to_sorted(&hcx, true)
});
tcx.arena.alloc_from_iter( tcx.arena.alloc_from_iter(
// This is based on: // This is based on:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63 // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174 // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
tcx.reachable_set(()).iter().filter_map(|&local_def_id| { reachable_set.into_iter().filter_map(|&local_def_id| {
// Do the same filtering that rustc does: // Do the same filtering that rustc does:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102 // https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
// Otherwise it may cause unexpected behaviours and ICEs // Otherwise it may cause unexpected behaviours and ICEs