Skip to content

Commit cde0f69

Browse files
committed
Fix stable iteration ordering for Map<Name, ...> usages
1 parent f2d5107 commit cde0f69

File tree

11 files changed

+55
-29
lines changed

11 files changed

+55
-29
lines changed

crates/hir-def/src/item_scope.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! Describes items defined or visible (ie, imported) in a certain scope.
22
//! This is shared between modules and blocks.
33
4-
use std::collections::hash_map::Entry;
5-
64
use base_db::CrateId;
75
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
6+
use indexmap::map::Entry;
87
use itertools::Itertools;
98
use la_arena::Idx;
109
use once_cell::sync::Lazy;
@@ -17,8 +16,8 @@ use crate::{
1716
db::DefDatabase,
1817
per_ns::PerNs,
1918
visibility::{Visibility, VisibilityExplicitness},
20-
AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId,
21-
ModuleDefId, ModuleId, TraitId, UseId,
19+
AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId,
20+
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
2221
};
2322

2423
#[derive(Debug, Default)]
@@ -67,9 +66,9 @@ pub struct ItemScope {
6766
/// Defs visible in this scope. This includes `declarations`, but also
6867
/// imports. The imports belong to this module and can be resolved by using them on
6968
/// the `use_imports_*` fields.
70-
types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
71-
values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
72-
macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
69+
types: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
70+
values: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
71+
macros: FxIndexMap<Name, (MacroId, Visibility, Option<ImportId>)>,
7372
unresolved: FxHashSet<Name>,
7473

7574
/// The defs declared in this scope. Each def has a single scope where it is
@@ -118,7 +117,7 @@ struct DeriveMacroInvocation {
118117
derive_call_ids: SmallVec<[Option<MacroCallId>; 1]>,
119118
}
120119

121-
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
120+
pub(crate) static BUILTIN_SCOPE: Lazy<FxIndexMap<Name, PerNs>> = Lazy::new(|| {
122121
BuiltinType::all_builtin_types()
123122
.iter()
124123
.map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))

crates/hir-def/src/nameres.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ pub struct ModuleData {
323323
///
324324
/// [`None`] for block modules because they are always its `DefMap`'s root.
325325
pub parent: Option<LocalModuleId>,
326-
pub children: FxHashMap<Name, LocalModuleId>,
326+
pub children: FxIndexMap<Name, LocalModuleId>,
327327
pub scope: ItemScope,
328328
}
329329

@@ -593,10 +593,8 @@ impl DefMap {
593593
self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
594594
}
595595

596-
pub(crate) fn macro_use_prelude(
597-
&self,
598-
) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
599-
self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
596+
pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
597+
&self.macro_use_prelude
600598
}
601599

602600
pub(crate) fn resolve_path(
@@ -668,7 +666,7 @@ impl ModuleData {
668666
origin,
669667
visibility,
670668
parent: None,
671-
children: FxHashMap::default(),
669+
children: Default::default(),
672670
scope: ItemScope::default(),
673671
}
674672
}

crates/hir-def/src/nameres/tests/macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
13481348
.keys()
13491349
.map(|name| name.display(&db).to_string())
13501350
.sorted()
1351+
.sorted()
13511352
.join("\n");
13521353

13531354
expect![[r#"

crates/hir-def/src/resolver.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{fmt, iter, mem};
44
use base_db::CrateId;
55
use hir_expand::{name::Name, MacroDefId};
66
use intern::{sym, Interned};
7+
use itertools::Itertools as _;
78
use rustc_hash::FxHashSet;
89
use smallvec::{smallvec, SmallVec};
910
use triomphe::Arc;
@@ -497,9 +498,11 @@ impl Resolver {
497498
res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)));
498499
})
499500
});
500-
def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| {
501-
res.add(name, ScopeDef::ModuleDef(def.into()));
502-
});
501+
def_map.macro_use_prelude().iter().sorted_by_key(|&(k, _)| k.clone()).for_each(
502+
|(name, &(def, _extern_crate))| {
503+
res.add(name, ScopeDef::ModuleDef(def.into()));
504+
},
505+
);
503506
def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
504507
res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
505508
});

crates/ide-assists/src/handlers/auto_import.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,8 +1637,8 @@ mod bar {
16371637

16381638
#[test]
16391639
fn local_inline_import_has_alias() {
1640-
// FIXME
1641-
check_assist_not_applicable(
1640+
// FIXME wrong import
1641+
check_assist(
16421642
auto_import,
16431643
r#"
16441644
struct S<T>(T);
@@ -1647,14 +1647,24 @@ use S as IoResult;
16471647
mod foo {
16481648
pub fn bar() -> S$0<()> {}
16491649
}
1650+
"#,
1651+
r#"
1652+
struct S<T>(T);
1653+
use S as IoResult;
1654+
1655+
mod foo {
1656+
use crate::S;
1657+
1658+
pub fn bar() -> S<()> {}
1659+
}
16501660
"#,
16511661
);
16521662
}
16531663

16541664
#[test]
16551665
fn alias_local() {
1656-
// FIXME
1657-
check_assist_not_applicable(
1666+
// FIXME wrong import
1667+
check_assist(
16581668
auto_import,
16591669
r#"
16601670
struct S<T>(T);
@@ -1663,6 +1673,16 @@ use S as IoResult;
16631673
mod foo {
16641674
pub fn bar() -> IoResult$0<()> {}
16651675
}
1676+
"#,
1677+
r#"
1678+
struct S<T>(T);
1679+
use S as IoResult;
1680+
1681+
mod foo {
1682+
use crate::S;
1683+
1684+
pub fn bar() -> IoResult<()> {}
1685+
}
16661686
"#,
16671687
);
16681688
}

crates/ide-completion/src/completions/format_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) fn format_string(
3131
};
3232

3333
let source_range = TextRange::new(brace_offset, cursor);
34-
ctx.locals.iter().for_each(|(name, _)| {
34+
ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()).for_each(|(name, _)| {
3535
CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
3636
.add_to(acc, ctx.db);
3737
});

crates/ide-completion/src/render/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ pub(super) fn add_call_parens<'b>(
259259

260260
fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str {
261261
if let Some(derefed_ty) = ty.remove_ref() {
262-
for (name, local) in ctx.locals.iter() {
262+
for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) {
263263
if name.as_str() == arg {
264264
return if local.ty(ctx.db) == derefed_ty {
265265
if ty.is_mutable_reference() {

crates/ide-completion/src/tests/flyimport.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,8 @@ fn main() {
767767
}
768768
"#,
769769
expect![[r#"
770-
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
771770
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
771+
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
772772
me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
773773
"#]],
774774
);

crates/ide-db/src/imports/import_assets.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::{
1515
use crate::{
1616
helpers::item_name,
1717
items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT},
18-
RootDatabase,
18+
FxIndexSet, RootDatabase,
1919
};
2020

2121
/// A candidate for import, derived during various IDE activities:
@@ -262,7 +262,7 @@ impl ImportAssets {
262262

263263
let scope = match sema.scope(&self.candidate_node) {
264264
Some(it) => it,
265-
None => return <FxHashSet<_>>::default().into_iter(),
265+
None => return <FxIndexSet<_>>::default().into_iter(),
266266
};
267267

268268
let krate = self.module_with_candidate.krate();
@@ -319,7 +319,7 @@ fn path_applicable_imports(
319319
path_candidate: &PathImportCandidate,
320320
mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy,
321321
scope_filter: impl Fn(ItemInNs) -> bool + Copy,
322-
) -> FxHashSet<LocatedImport> {
322+
) -> FxIndexSet<LocatedImport> {
323323
let _p = tracing::info_span!("ImportAssets::path_applicable_imports").entered();
324324

325325
match &path_candidate.qualifier {
@@ -500,7 +500,7 @@ fn trait_applicable_items(
500500
trait_assoc_item: bool,
501501
mod_path: impl Fn(ItemInNs) -> Option<ModPath>,
502502
scope_filter: impl Fn(hir::Trait) -> bool,
503-
) -> FxHashSet<LocatedImport> {
503+
) -> FxIndexSet<LocatedImport> {
504504
let _p = tracing::info_span!("ImportAssets::trait_applicable_items").entered();
505505

506506
let db = sema.db;
@@ -566,7 +566,7 @@ fn trait_applicable_items(
566566
definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate()
567567
});
568568

569-
let mut located_imports = FxHashSet::default();
569+
let mut located_imports = FxIndexSet::default();
570570
let mut trait_import_paths = FxHashMap::default();
571571

572572
if trait_assoc_item {

crates/intern/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const _: () =
3737
/// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or
3838
/// `Arc<Box<str>>` but its size is that of a thin pointer. The active variant is encoded as a tag
3939
/// in the LSB of the alignment niche.
40+
// Note, Ideally this would encode a `ThinArc<str>` and `ThinRef<str>`/`ThinConstPtr<str>` instead of the double indirection.
4041
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
4142
struct TaggedArcPtr {
4243
packed: NonNull<*const str>,

crates/intern/src/symbol/symbols.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use crate::{
1313

1414
macro_rules! define_symbols {
1515
(@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => {
16+
// Ideally we would be emitting `const` here, but then we no longer have stable addresses
17+
// which is what we are relying on for equality! In the future if consts can refer to
18+
// statics we should swap these for `const`s and have the the string literal being pointed
19+
// to be statics to refer to such that their address is stable.
1620
$(
1721
pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) };
1822
)*

0 commit comments

Comments
 (0)