1
Fork 0

Rollup merge of #136901 - workingjubilee:stabilize-externabi-hashing-forever, r=compiler-errors

compiler: give `ExternAbi` truly stable `Hash` and `Ord`

Currently, `ExternAbi` has a bunch of code to handle the reality that, as an enum, adding more variants to it will risk it hashing differently. It forces all of those variants to be added in a fixed order, except this means that the order of the variants doesn't correspond to any logical order except "historical accident". This is all to avoid having to rebless two tests. Perhaps there were more, once upon a time? But then we invented normalization in our test suite to handle exactly this sort of issue in a more general way.

There are two options here:
- Get rid of all the logical overhead and shrug, embracing blessing a couple of tests sometimes
- Change `ExternAbi` to have an ordering and hash that doesn't depend on the number of variants

As `ExternAbi` is essentially a strongly-typed string, and thus no two strings can be identical, this implements the second of the two by hand-implementing `Ord` and `Hash` to make the hashing and comparison based on the string! This will diff the current hashes, but they will diff no more after this.
This commit is contained in:
Guillaume Gomez 2025-02-12 20:30:55 +01:00 committed by GitHub
commit 27dc222fb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 163 additions and 176 deletions

View file

@ -1475,7 +1475,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {
let ast::StrLit { symbol_unescaped, span, .. } = abi_str;
let extern_abi = rustc_abi::lookup(symbol_unescaped.as_str()).unwrap_or_else(|_| {
let extern_abi = symbol_unescaped.as_str().parse().unwrap_or_else(|_| {
self.error_on_invalid_abi(abi_str);
ExternAbi::Rust
});

View file

@ -8,10 +8,10 @@ use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
pub(crate) fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
rustc_abi::AbiDatas
.iter()
.filter(|data| extern_abi_enabled(features, span, data.abi).is_ok())
.map(|d| d.name)
ExternAbi::ALL_VARIANTS
.into_iter()
.filter(|abi| extern_abi_enabled(features, span, **abi).is_ok())
.map(|abi| abi.as_str())
.collect()
}
@ -54,17 +54,12 @@ enum GateReason {
impl fmt::Display for UnstableAbi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { abi, .. } = self;
let name = abi.to_string();
let name = name.trim_matches('"');
match self.explain {
GateReason::Experimental => {
write!(f, r#"the extern "{name}" ABI is experimental and subject to change"#)
write!(f, "the extern {abi} ABI is experimental and subject to change")
}
GateReason::ImplDetail => {
write!(
f,
r#"the extern "{name}" ABI is an implementation detail and perma-unstable"#
)
write!(f, "the extern {abi} ABI is an implementation detail and perma-unstable")
}
}
}