Skip to content

Commit 0f8534e

Browse files
committed
Auto merge of #120812 - compiler-errors:impl-sorting, r=lcnr
Remove unnecessary impl sorting in queries and metadata Removes unnecessary impl sorting because queries already return their keys in HIR definition order: #120371 (comment) r? `@cjgillot` or `@lcnr` -- unless I totally misunderstood what was being asked for here? 😆 fixes #120371
2 parents 92c6c03 + e0ba193 commit 0f8534e

File tree

10 files changed

+75
-95
lines changed

10 files changed

+75
-95
lines changed

compiler/rustc_infer/src/traits/error_reporting/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,12 @@ pub fn report_object_safety_error<'tcx>(
177177
)));
178178
}
179179
impls => {
180-
let mut types = impls
180+
let types = impls
181181
.iter()
182182
.map(|t| {
183183
with_no_trimmed_paths!(format!(" {}", tcx.type_of(*t).instantiate_identity(),))
184184
})
185185
.collect::<Vec<_>>();
186-
types.sort();
187186
err.help(format!(
188187
"the following types implement the trait, consider defining an enum where each \
189188
variant holds one of these types, implementing `{}` for this new enum and using \

compiler/rustc_metadata/src/rmeta/decoder.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::rmeta::*;
77
use rustc_ast as ast;
88
use rustc_data_structures::captures::Captures;
99
use rustc_data_structures::fingerprint::Fingerprint;
10+
use rustc_data_structures::fx::FxIndexMap;
1011
use rustc_data_structures::owned_slice::OwnedSlice;
1112
use rustc_data_structures::sync::{Lock, Lrc, OnceLock};
1213
use rustc_data_structures::unhash::UnhashMap;
@@ -83,12 +84,12 @@ pub(crate) struct CrateMetadata {
8384
/// Trait impl data.
8485
/// FIXME: Used only from queries and can use query cache,
8586
/// so pre-decoding can probably be avoided.
86-
trait_impls: FxHashMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
87+
trait_impls: FxIndexMap<(u32, DefIndex), LazyArray<(DefIndex, Option<SimplifiedType>)>>,
8788
/// Inherent impls which do not follow the normal coherence rules.
8889
///
8990
/// These can be introduced using either `#![rustc_coherence_is_core]`
9091
/// or `#[rustc_allow_incoherent_impl]`.
91-
incoherent_impls: FxHashMap<SimplifiedType, LazyArray<DefIndex>>,
92+
incoherent_impls: FxIndexMap<SimplifiedType, LazyArray<DefIndex>>,
9293
/// Proc macro descriptions for this crate, if it's a proc macro crate.
9394
raw_proc_macros: Option<&'static [ProcMacro]>,
9495
/// Source maps for code from the crate.

compiler/rustc_metadata/src/rmeta/encoder.rs

+18-65
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::errors::{FailCreateFileEncoder, FailWriteFile};
22
use crate::rmeta::*;
33

44
use rustc_ast::Attribute;
5-
use rustc_data_structures::fx::FxIndexSet;
5+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
66
use rustc_data_structures::memmap::{Mmap, MmapMut};
77
use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
88
use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -13,7 +13,6 @@ use rustc_hir_pretty::id_to_string;
1313
use rustc_middle::middle::dependency_format::Linkage;
1414
use rustc_middle::middle::exported_symbols::metadata_symbol_name;
1515
use rustc_middle::mir::interpret;
16-
use rustc_middle::query::LocalCrate;
1716
use rustc_middle::query::Providers;
1817
use rustc_middle::traits::specialization_graph;
1918
use rustc_middle::ty::codec::TyEncoder;
@@ -1509,10 +1508,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15091508
}
15101509
}
15111510

1512-
let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
1513-
tcx.crate_inherent_impls(()).unwrap().inherent_impls.to_sorted(&hcx, true)
1514-
});
1515-
for (def_id, impls) in inherent_impls {
1511+
for (def_id, impls) in &tcx.crate_inherent_impls(()).unwrap().inherent_impls {
15161512
record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
15171513
assert!(def_id.is_local());
15181514
def_id.index
@@ -2002,8 +1998,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20021998
fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
20031999
empty_proc_macro!(self);
20042000
let tcx = self.tcx;
2005-
let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
2006-
FxHashMap::default();
2001+
let mut trait_impls: FxIndexMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
2002+
FxIndexMap::default();
20072003

20082004
for id in tcx.hir().items() {
20092005
let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
@@ -2022,7 +2018,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20222018
trait_ref.self_ty(),
20232019
TreatParams::AsCandidateKey,
20242020
);
2025-
fx_hash_map
2021+
trait_impls
20262022
.entry(trait_ref.def_id)
20272023
.or_default()
20282024
.push((id.owner_id.def_id.local_def_index, simplified_self_ty));
@@ -2043,47 +2039,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20432039
}
20442040
}
20452041

2046-
let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
2047-
2048-
// Bring everything into deterministic order for hashing
2049-
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
2050-
2051-
let all_impls: Vec<_> = all_impls
2042+
let trait_impls: Vec<_> = trait_impls
20522043
.into_iter()
2053-
.map(|(trait_def_id, mut impls)| {
2054-
// Bring everything into deterministic order for hashing
2055-
impls.sort_by_cached_key(|&(index, _)| {
2056-
tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
2057-
});
2058-
2059-
TraitImpls {
2060-
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
2061-
impls: self.lazy_array(&impls),
2062-
}
2044+
.map(|(trait_def_id, impls)| TraitImpls {
2045+
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
2046+
impls: self.lazy_array(&impls),
20632047
})
20642048
.collect();
20652049

2066-
self.lazy_array(&all_impls)
2050+
self.lazy_array(&trait_impls)
20672051
}
20682052

20692053
#[instrument(level = "debug", skip(self))]
20702054
fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
20712055
empty_proc_macro!(self);
20722056
let tcx = self.tcx;
2073-
let all_impls = tcx.with_stable_hashing_context(|hcx| {
2074-
tcx.crate_inherent_impls(()).unwrap().incoherent_impls.to_sorted(&hcx, true)
2075-
});
20762057

2077-
let all_impls: Vec<_> = all_impls
2078-
.into_iter()
2079-
.map(|(&simp, impls)| {
2080-
let mut impls: Vec<_> =
2081-
impls.into_iter().map(|def_id| def_id.local_def_index).collect();
2082-
impls.sort_by_cached_key(|&local_def_index| {
2083-
tcx.hir().def_path_hash(LocalDefId { local_def_index })
2084-
});
2085-
2086-
IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
2058+
let all_impls: Vec<_> = tcx
2059+
.crate_inherent_impls(())
2060+
.unwrap()
2061+
.incoherent_impls
2062+
.iter()
2063+
.map(|(&simp, impls)| IncoherentImpls {
2064+
self_ty: simp,
2065+
impls: self.lazy_array(impls.iter().map(|def_id| def_id.local_def_index)),
20872066
})
20882067
.collect();
20892068

@@ -2327,32 +2306,6 @@ pub fn provide(providers: &mut Providers) {
23272306
span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
23282307
})
23292308
},
2330-
traits: |tcx, LocalCrate| {
2331-
let mut traits = Vec::new();
2332-
for id in tcx.hir().items() {
2333-
if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
2334-
traits.push(id.owner_id.to_def_id())
2335-
}
2336-
}
2337-
2338-
// Bring everything into deterministic order.
2339-
traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
2340-
tcx.arena.alloc_slice(&traits)
2341-
},
2342-
trait_impls_in_crate: |tcx, LocalCrate| {
2343-
let mut trait_impls = Vec::new();
2344-
for id in tcx.hir().items() {
2345-
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
2346-
&& tcx.impl_trait_ref(id.owner_id).is_some()
2347-
{
2348-
trait_impls.push(id.owner_id.to_def_id())
2349-
}
2350-
}
2351-
2352-
// Bring everything into deterministic order.
2353-
trait_impls.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
2354-
tcx.arena.alloc_slice(&trait_impls)
2355-
},
23562309

23572310
..*providers
23582311
}

compiler/rustc_middle/src/ty/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ use rustc_data_structures::intern::Interned;
4040
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
4141
use rustc_data_structures::steal::Steal;
4242
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
43-
use rustc_data_structures::unord::UnordMap;
4443
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
4544
use rustc_hir as hir;
4645
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
@@ -2083,6 +2082,8 @@ pub fn provide(providers: &mut Providers) {
20832082
*providers = Providers {
20842083
trait_impls_of: trait_def::trait_impls_of_provider,
20852084
incoherent_impls: trait_def::incoherent_impls_provider,
2085+
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
2086+
traits: trait_def::traits_provider,
20862087
const_param_default: consts::const_param_default,
20872088
vtable_allocation: vtable::vtable_allocation_provider,
20882089
..*providers
@@ -2096,8 +2097,8 @@ pub fn provide(providers: &mut Providers) {
20962097
/// (constructing this map requires touching the entire crate).
20972098
#[derive(Clone, Debug, Default, HashStable)]
20982099
pub struct CrateInherentImpls {
2099-
pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
2100-
pub incoherent_impls: UnordMap<SimplifiedType, Vec<LocalDefId>>,
2100+
pub inherent_impls: FxIndexMap<LocalDefId, Vec<DefId>>,
2101+
pub incoherent_impls: FxIndexMap<SimplifiedType, Vec<LocalDefId>>,
21012102
}
21022103

21032104
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]

compiler/rustc_middle/src/ty/trait_def.rs

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
use crate::traits::specialization_graph;
2-
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
3-
use crate::ty::{Ident, Ty, TyCtxt};
4-
use hir::def_id::LOCAL_CRATE;
5-
use rustc_hir as hir;
6-
use rustc_hir::def_id::DefId;
71
use std::iter;
82
use tracing::debug;
93

104
use rustc_data_structures::fx::FxIndexMap;
115
use rustc_errors::ErrorGuaranteed;
6+
use rustc_hir as hir;
7+
use rustc_hir::def::DefKind;
8+
use rustc_hir::def_id::DefId;
9+
use rustc_hir::def_id::LOCAL_CRATE;
1210
use rustc_macros::{Decodable, Encodable, HashStable};
1311

12+
use crate::query::LocalCrate;
13+
use crate::traits::specialization_graph;
14+
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
15+
use crate::ty::{Ident, Ty, TyCtxt};
16+
1417
/// A trait's definition with type information.
1518
#[derive(HashStable, Encodable, Decodable)]
1619
pub struct TraitDef {
@@ -274,3 +277,27 @@ pub(super) fn incoherent_impls_provider(
274277

275278
Ok(tcx.arena.alloc_slice(&impls))
276279
}
280+
281+
pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
282+
let mut traits = Vec::new();
283+
for id in tcx.hir().items() {
284+
if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
285+
traits.push(id.owner_id.to_def_id())
286+
}
287+
}
288+
289+
tcx.arena.alloc_slice(&traits)
290+
}
291+
292+
pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
293+
let mut trait_impls = Vec::new();
294+
for id in tcx.hir().items() {
295+
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
296+
&& tcx.impl_trait_ref(id.owner_id).is_some()
297+
{
298+
trait_impls.push(id.owner_id.to_def_id())
299+
}
300+
}
301+
302+
tcx.arena.alloc_slice(&trait_impls)
303+
}

src/tools/clippy/clippy_lints/src/inherent_impl.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,18 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
5656
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
5757
return;
5858
};
59-
let inherent_impls = cx
60-
.tcx
61-
.with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
6259

63-
for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
64-
impls.len() > 1
60+
for (&id, impl_ids) in &impls.inherent_impls {
61+
if impl_ids.len() < 2
6562
// Check for `#[allow]` on the type definition
66-
&& !is_lint_allowed(
63+
|| is_lint_allowed(
6764
cx,
6865
MULTIPLE_INHERENT_IMPL,
6966
cx.tcx.local_def_id_to_hir_id(id),
70-
)
71-
}) {
67+
) {
68+
continue;
69+
}
70+
7271
for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
7372
let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity();
7473
match type_map.entry(impl_ty) {

tests/rustdoc/anchor-id-duplicate-method-name-25001.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ impl Foo<u32> {
2424
}
2525

2626
impl<T> Bar for Foo<T> {
27-
//@ has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' 'type Item = T'
27+
// @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' 'type Item = T'
2828
type Item=T;
2929

3030
//@ has - '//*[@id="method.quux"]//h4[@class="code-header"]' 'fn quux(self)'
3131
fn quux(self) {}
3232
}
3333
impl<'a, T> Bar for &'a Foo<T> {
34-
//@ has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item = &'a T"
34+
// @has - '//*[@id="associatedtype.Item-1"]//h4[@class="code-header"]' "type Item = &'a T"
3535
type Item=&'a T;
3636

3737
//@ has - '//*[@id="method.quux-1"]//h4[@class="code-header"]' 'fn quux(self)'

tests/ui/generic-associated-types/gat-in-trait-path.base.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ LL | type A<'a> where Self: 'a;
1313
| ^ ...because it contains the generic associated type `A`
1414
= help: consider moving `A` to another trait
1515
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
16-
Fooer<T>
1716
Fooy
17+
Fooer<T>
1818

1919
error[E0038]: the trait `Foo` cannot be made into an object
2020
--> $DIR/gat-in-trait-path.rs:32:5
@@ -31,8 +31,8 @@ LL | type A<'a> where Self: 'a;
3131
| ^ ...because it contains the generic associated type `A`
3232
= help: consider moving `A` to another trait
3333
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
34-
Fooer<T>
3534
Fooy
35+
Fooer<T>
3636

3737
error[E0038]: the trait `Foo` cannot be made into an object
3838
--> $DIR/gat-in-trait-path.rs:32:5
@@ -49,8 +49,8 @@ LL | type A<'a> where Self: 'a;
4949
| ^ ...because it contains the generic associated type `A`
5050
= help: consider moving `A` to another trait
5151
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
52-
Fooer<T>
5352
Fooy
53+
Fooer<T>
5454
= note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A = &'a ()> + 'static)>`
5555

5656
error: aborting due to 3 previous errors

tests/ui/generic-associated-types/issue-79422.base.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
2929
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
3030
= help: consider moving `VRefCont` to another trait
3131
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
32-
Source
3332
std::collections::BTreeMap<K, V>
33+
Source
3434

3535
error[E0038]: the trait `MapLike` cannot be made into an object
3636
--> $DIR/issue-79422.rs:44:13
@@ -47,8 +47,8 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
4747
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
4848
= help: consider moving `VRefCont` to another trait
4949
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
50-
Source
5150
std::collections::BTreeMap<K, V>
51+
Source
5252
= note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
5353

5454
error: aborting due to 3 previous errors

tests/ui/wf/wf-unsafe-trait-obj-match.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ LL | trait Trait: Sized {}
2626
| |
2727
| this trait cannot be made into an object...
2828
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
29-
R
3029
S
30+
R
3131
= note: required for the cast from `&S` to `&dyn Trait`
3232

3333
error[E0038]: the trait `Trait` cannot be made into an object
@@ -48,8 +48,8 @@ LL | trait Trait: Sized {}
4848
| |
4949
| this trait cannot be made into an object...
5050
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead:
51-
R
5251
S
52+
R
5353
= note: required for the cast from `&R` to `&dyn Trait`
5454

5555
error: aborting due to 3 previous errors

0 commit comments

Comments
 (0)