impl !PartialOrd for HirId

This commit is contained in:
Oli Scherer 2025-03-17 12:23:53 +00:00
parent 5a4e7eb040
commit 57c4ab7ff5
5 changed files with 44 additions and 32 deletions

View file

@ -83,6 +83,12 @@ pub struct HirId {
pub local_id: ItemLocalId,
}
// To ensure correctness of incremental compilation,
// `HirId` must not implement `Ord` or `PartialOrd`.
// See https://github.com/rust-lang/rust/issues/90317.
impl !Ord for HirId {}
impl !PartialOrd for HirId {}
impl Debug for HirId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10)
@ -116,10 +122,6 @@ impl HirId {
pub fn make_owner(owner: LocalDefId) -> Self {
Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::ZERO }
}
pub fn index(self) -> (usize, usize) {
(rustc_index::Idx::index(self.owner.def_id), rustc_index::Idx::index(self.local_id))
}
}
impl fmt::Display for HirId {
@ -128,18 +130,6 @@ impl fmt::Display for HirId {
}
}
impl Ord for HirId {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(self.index()).cmp(&(other.index()))
}
}
impl PartialOrd for HirId {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId);
rustc_data_structures::define_id_collections!(
ItemLocalMap,

View file

@ -11,6 +11,7 @@
#![feature(debug_closure_helpers)]
#![feature(exhaustive_patterns)]
#![feature(let_chains)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![feature(variant_count)]

View file

@ -8,7 +8,8 @@ use rustc_data_structures::stable_hasher::{
};
use rustc_error_messages::{DiagMessage, MultiSpan};
use rustc_hir::def::Namespace;
use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
use rustc_hir::def_id::DefPathHash;
use rustc_hir::{HashStableContext, HirId, ItemLocalId, MissingLifetimeKind};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
pub use rustc_span::edition::Edition;
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym};
@ -102,7 +103,7 @@ pub enum Applicability {
/// The index values have a type of `u16` to reduce the size of the `LintExpectationId`.
/// It's reasonable to assume that no user will define 2^16 attributes on one node or
/// have that amount of lints listed. `u16` values should therefore suffice.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, Encodable, Decodable)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Encodable, Decodable)]
pub enum LintExpectationId {
/// Used for lints emitted during the `EarlyLintPass`. This id is not
/// hash stable and should not be cached.
@ -156,13 +157,14 @@ impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId {
}
impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectationId {
type KeyType = (HirId, u16, u16);
type KeyType = (DefPathHash, ItemLocalId, u16, u16);
#[inline]
fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType {
match self {
LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
(*hir_id, *attr_index, *lint_index)
let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx);
(def_path_hash, lint_idx, *attr_index, *lint_index)
}
_ => {
unreachable!("HashStable should only be called for a filled `LintExpectationId`")

View file

@ -1130,7 +1130,8 @@ impl<'tcx> DeadVisitor<'tcx> {
if dead_codes.is_empty() {
return;
}
dead_codes.sort_by_key(|v| v.level);
// FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>`
dead_codes.sort_by_key(|v| v.level.0);
for group in dead_codes.chunk_by(|a, b| a.level == b.level) {
self.lint_at_single_level(&group, participle, Some(def_id), report_on);
}

View file

@ -153,9 +153,15 @@ impl LateLintPass<'_> for MacroUseImports {
[] | [_] => return,
[root, item] => {
if !check_dup.contains(&(*item).to_string()) {
used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new)
.push((*item).to_string());
used.entry((
(*root).to_string(),
span,
hir_id.local_id,
cx.tcx.def_path_hash(hir_id.owner.def_id.into()),
))
.or_insert_with(|| (vec![], hir_id))
.0
.push((*item).to_string());
check_dup.push((*item).to_string());
}
},
@ -171,15 +177,27 @@ impl LateLintPass<'_> for MacroUseImports {
}
})
.collect::<Vec<_>>();
used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new)
.push(filtered.join("::"));
used.entry((
(*root).to_string(),
span,
hir_id.local_id,
cx.tcx.def_path_hash(hir_id.owner.def_id.into()),
))
.or_insert_with(|| (vec![], hir_id))
.0
.push(filtered.join("::"));
check_dup.extend(filtered);
} else {
let rest = rest.to_vec();
used.entry(((*root).to_string(), span, hir_id))
.or_insert_with(Vec::new)
.push(rest.join("::"));
used.entry((
(*root).to_string(),
span,
hir_id.local_id,
cx.tcx.def_path_hash(hir_id.owner.def_id.into()),
))
.or_insert_with(|| (vec![], hir_id))
.0
.push(rest.join("::"));
check_dup.extend(rest.iter().map(ToString::to_string));
}
},
@ -190,7 +208,7 @@ impl LateLintPass<'_> for MacroUseImports {
// If mac_refs is not empty we have encountered an import we could not handle
// such as `std::prelude::v1::foo` or some other macro that expands to an import.
if self.mac_refs.is_empty() {
for ((root, span, hir_id), path) in used {
for ((root, span, ..), (path, hir_id)) in used {
let import = if let [single] = &path[..] {
format!("{root}::{single}")
} else {