about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2022-09-27 15:21:31 -0700
committerJosh Stone <jistone@redhat.com>2022-09-27 15:21:31 -0700
commitfb5002d68aa22f23ced3e2b5265f622264e4840a (patch)
tree7ac8346a53e6a207bc872985a400525e8d742257
parent57ee5cf5a93923dae9c98bffb11545fc3a31368d (diff)
downloadrust-fb5002d68aa22f23ced3e2b5265f622264e4840a.tar.gz
rust-fb5002d68aa22f23ced3e2b5265f622264e4840a.zip
Manually order `DefId` on 64-bit big-endian
`DefId` uses different field orders on 64-bit big-endian vs. others, in
order to optimize its `Hash` implementation. However, that also made it
derive different lexical ordering for `PartialOrd` and `Ord`. That
caused spurious differences wherever `DefId`s are sorted, like the
candidate sources list in `report_method_error`.

Now we manually implement `PartialOrd` and `Ord` on 64-bit big-endian to
match the same lexical ordering as other targets, fixing at least one
test, `src/test/ui/methods/method-ambig-two-traits-cross-crate.rs`.
-rw-r--r--compiler/rustc_span/src/def_id.rs20
1 files changed, 19 insertions, 1 deletions
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 37b8371a8fe..bbeabdb55a7 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -218,7 +218,9 @@ impl<D: Decoder> Decodable<D> for DefIndex {
 /// index and a def index.
 ///
 /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)]
+#[derive(Clone, PartialEq, Eq, Copy)]
+// Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order.
+#[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))]
 // On below-64 bit systems we can simply use the derived `Hash` impl
 #[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
 #[repr(C)]
@@ -260,6 +262,22 @@ impl Hash for DefId {
     }
 }
 
+// Implement the same comparison as derived with the other field order.
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl Ord for DefId {
+    #[inline]
+    fn cmp(&self, other: &DefId) -> std::cmp::Ordering {
+        Ord::cmp(&(self.index, self.krate), &(other.index, other.krate))
+    }
+}
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl PartialOrd for DefId {
+    #[inline]
+    fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
+        Some(Ord::cmp(self, other))
+    }
+}
+
 impl DefId {
     /// Makes a local `DefId` from the given `DefIndex`.
     #[inline]