Skip to content

Commit 33b49c9

Browse files
authored
shorten comment on Ord for SourceKind (#15029)
As discussed in today's cargo meeting, and in https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/while.20we're.20breaking.20stable.20hash, we are keeping the manual impl but shortening the comment about why it is needed.
2 parents d9f65ec + 06811d8 commit 33b49c9

File tree

4 files changed

+54
-81
lines changed

4 files changed

+54
-81
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cargo-util-schemas/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cargo-util-schemas"
3-
version = "0.7.2"
3+
version = "0.7.3"
44
rust-version = "1.83" # MSRV:1
55
edition.workspace = true
66
license.workspace = true

crates/cargo-util-schemas/src/core/source_kind.rs

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::cmp::Ordering;
22

33
/// The possible kinds of code source.
4-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4+
#[derive(Debug, Clone, PartialEq, Eq)]
55
pub enum SourceKind {
66
/// A git repository.
77
Git(GitReference),
@@ -17,6 +17,19 @@ pub enum SourceKind {
1717
Directory,
1818
}
1919

20+
// The hash here is important for what folder packages get downloaded into.
21+
// Changes trigger all users to download another copy of their crates.
22+
// So the `stable_hash` test checks that we only change it intentionally.
23+
// We implement hash manually to callout the stability impact.
24+
impl std::hash::Hash for SourceKind {
25+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
26+
core::mem::discriminant(self).hash(state);
27+
if let SourceKind::Git(git) = self {
28+
git.hash(state);
29+
}
30+
}
31+
}
32+
2033
impl SourceKind {
2134
pub fn protocol(&self) -> Option<&str> {
2235
match self {
@@ -31,59 +44,9 @@ impl SourceKind {
3144
}
3245
}
3346

34-
/// Note that this is specifically not derived on `SourceKind` although the
35-
/// implementation here is very similar to what it might look like if it were
36-
/// otherwise derived.
37-
///
38-
/// The reason for this is somewhat obtuse. First of all the hash value of
39-
/// `SourceKind` makes its way into `~/.cargo/registry/index/github.com-XXXX`
40-
/// which means that changes to the hash means that all Rust users need to
41-
/// redownload the crates.io index and all their crates. If possible we strive
42-
/// to not change this to make this redownloading behavior happen as little as
43-
/// possible. How is this connected to `Ord` you might ask? That's a good
44-
/// question!
45-
///
46-
/// Since the beginning of time `SourceKind` has had `#[derive(Hash)]`. It for
47-
/// the longest time *also* derived the `Ord` and `PartialOrd` traits. In #8522,
48-
/// however, the implementation of `Ord` changed. This handwritten implementation
49-
/// forgot to sync itself with the originally derived implementation, namely
50-
/// placing git dependencies as sorted after all other dependencies instead of
51-
/// first as before.
52-
///
53-
/// This regression in #8522 (Rust 1.47) went unnoticed. When we switched back
54-
/// to a derived implementation in #9133 (Rust 1.52 beta) we only then ironically
55-
/// saw an issue (#9334). In #9334 it was observed that stable Rust at the time
56-
/// (1.51) was sorting git dependencies last, whereas Rust 1.52 beta would sort
57-
/// git dependencies first. This is because the `PartialOrd` implementation in
58-
/// 1.51 used #8522, the buggy implementation, which put git deps last. In 1.52
59-
/// it was (unknowingly) restored to the pre-1.47 behavior with git dependencies
60-
/// first.
61-
///
62-
/// Because the breakage was only witnessed after the original breakage, this
63-
/// trait implementation is preserving the "broken" behavior. Put a different way:
64-
///
65-
/// * Rust pre-1.47 sorted git deps first.
66-
/// * Rust 1.47 to Rust 1.51 sorted git deps last, a breaking change (#8522) that
67-
/// was never noticed.
68-
/// * Rust 1.52 restored the pre-1.47 behavior (#9133, without knowing it did
69-
/// so), and breakage was witnessed by actual users due to difference with
70-
/// 1.51.
71-
/// * Rust 1.52 (the source as it lives now) was fixed to match the 1.47-1.51
72-
/// behavior (#9383), which is now considered intentionally breaking from the
73-
/// pre-1.47 behavior.
74-
///
75-
/// Note that this was all discovered when Rust 1.53 was in nightly and 1.52 was
76-
/// in beta. #9133 was in both beta and nightly at the time of discovery. For
77-
/// 1.52 #9383 reverted #9133, meaning 1.52 is the same as 1.51. On nightly
78-
/// (1.53) #9397 was created to fix the regression introduced by #9133 relative
79-
/// to the current stable (1.51).
80-
///
81-
/// That's all a long winded way of saying "it's weird that git deps hash first
82-
/// and are sorted last, but it's the way it is right now". The author of this
83-
/// comment chose to handwrite the `Ord` implementation instead of the `Hash`
84-
/// implementation, but it's only required that at most one of them is
85-
/// hand-written because the other can be derived. Perhaps one day in
86-
/// the future someone can figure out how to remove this behavior.
47+
// The ordering here is important for how packages are serialized into lock files.
48+
// We implement it manually to callout the stability guarantee.
49+
// See https://github.com/rust-lang/cargo/pull/9397 for the history.
8750
impl Ord for SourceKind {
8851
fn cmp(&self, other: &SourceKind) -> Ordering {
8952
match (self, other) {

src/cargo/core/source_id.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ mod tests {
762762
// value.
763763
//
764764
// Note that the hash value matches what the crates.io source id has hashed
765-
// since long before Rust 1.30. We strive to keep this value the same across
765+
// since Rust 1.84.0. We strive to keep this value the same across
766766
// versions of Cargo because changing it means that users will need to
767767
// redownload the index and all crates they use when using a new Cargo version.
768768
//
@@ -771,6 +771,11 @@ mod tests {
771771
// you're able to restore the hash to its original value, please do so!
772772
// Otherwise please just leave a comment in your PR as to why the hash value is
773773
// changing and why the old value can't be easily preserved.
774+
// If it takes an ugly hack to restore it,
775+
// then leave a link here so we can remove the hack next time we change the hash.
776+
//
777+
// Hacks to remove next time the hash changes:
778+
// - (fill in your code here)
774779
//
775780
// The hash value should be stable across platforms, and doesn't depend on
776781
// endianness and bit-width. One caveat is that absolute paths on Windows
@@ -782,6 +787,11 @@ mod tests {
782787
use std::hash::Hasher;
783788
use std::path::Path;
784789

790+
use snapbox::assert_data_eq;
791+
use snapbox::str;
792+
use snapbox::IntoData as _;
793+
794+
use crate::util::hex::short_hash;
785795
use crate::util::StableHasher;
786796

787797
#[cfg(not(windows))]
@@ -792,68 +802,68 @@ mod tests {
792802
let gen_hash = |source_id: SourceId| {
793803
let mut hasher = StableHasher::new();
794804
source_id.stable_hash(ws_root, &mut hasher);
795-
Hasher::finish(&hasher)
805+
Hasher::finish(&hasher).to_string()
796806
};
797807

798808
let source_id = SourceId::crates_io(&GlobalContext::default().unwrap()).unwrap();
799-
assert_eq!(gen_hash(source_id), 7062945687441624357);
800-
assert_eq!(crate::util::hex::short_hash(&source_id), "25cdd57fae9f0462");
809+
assert_data_eq!(gen_hash(source_id), str!["7062945687441624357"].raw());
810+
assert_data_eq!(short_hash(&source_id), str!["25cdd57fae9f0462"].raw());
801811

802812
let url = "https://my-crates.io".into_url().unwrap();
803813
let source_id = SourceId::for_registry(&url).unwrap();
804-
assert_eq!(gen_hash(source_id), 8310250053664888498);
805-
assert_eq!(crate::util::hex::short_hash(&source_id), "b2d65deb64f05373");
814+
assert_data_eq!(gen_hash(source_id), str!["8310250053664888498"].raw());
815+
assert_data_eq!(short_hash(&source_id), str!["b2d65deb64f05373"].raw());
806816

807817
let url = "https://your-crates.io".into_url().unwrap();
808818
let source_id = SourceId::for_alt_registry(&url, "alt").unwrap();
809-
assert_eq!(gen_hash(source_id), 14149534903000258933);
810-
assert_eq!(crate::util::hex::short_hash(&source_id), "755952de063f5dc4");
819+
assert_data_eq!(gen_hash(source_id), str!["14149534903000258933"].raw());
820+
assert_data_eq!(short_hash(&source_id), str!["755952de063f5dc4"].raw());
811821

812822
let url = "sparse+https://my-crates.io".into_url().unwrap();
813823
let source_id = SourceId::for_registry(&url).unwrap();
814-
assert_eq!(gen_hash(source_id), 16249512552851930162);
815-
assert_eq!(crate::util::hex::short_hash(&source_id), "327cfdbd92dd81e1");
824+
assert_data_eq!(gen_hash(source_id), str!["16249512552851930162"].raw());
825+
assert_data_eq!(short_hash(&source_id), str!["327cfdbd92dd81e1"].raw());
816826

817827
let url = "sparse+https://your-crates.io".into_url().unwrap();
818828
let source_id = SourceId::for_alt_registry(&url, "alt").unwrap();
819-
assert_eq!(gen_hash(source_id), 6156697384053352292);
820-
assert_eq!(crate::util::hex::short_hash(&source_id), "64a713b6a6fb7055");
829+
assert_data_eq!(gen_hash(source_id), str!["6156697384053352292"].raw());
830+
assert_data_eq!(short_hash(&source_id), str!["64a713b6a6fb7055"].raw());
821831

822832
let url = "file:///tmp/ws/crate".into_url().unwrap();
823833
let source_id = SourceId::for_git(&url, GitReference::DefaultBranch).unwrap();
824-
assert_eq!(gen_hash(source_id), 473480029881867801);
825-
assert_eq!(crate::util::hex::short_hash(&source_id), "199e591d94239206");
834+
assert_data_eq!(gen_hash(source_id), str!["473480029881867801"].raw());
835+
assert_data_eq!(short_hash(&source_id), str!["199e591d94239206"].raw());
826836

827837
let path = &ws_root.join("crate");
828838
let source_id = SourceId::for_local_registry(path).unwrap();
829839
#[cfg(not(windows))]
830840
{
831-
assert_eq!(gen_hash(source_id), 11515846423845066584);
832-
assert_eq!(crate::util::hex::short_hash(&source_id), "58d73c154f81d09f");
841+
assert_data_eq!(gen_hash(source_id), str!["11515846423845066584"].raw());
842+
assert_data_eq!(short_hash(&source_id), str!["58d73c154f81d09f"].raw());
833843
}
834844
#[cfg(windows)]
835845
{
836-
assert_eq!(gen_hash(source_id), 6146331155906064276);
837-
assert_eq!(crate::util::hex::short_hash(&source_id), "946fb2239f274c55");
846+
assert_data_eq!(gen_hash(source_id), str!["6146331155906064276"].raw());
847+
assert_data_eq!(short_hash(&source_id), str!["946fb2239f274c55"].raw());
838848
}
839849

840850
let source_id = SourceId::for_path(path).unwrap();
841-
assert_eq!(gen_hash(source_id), 215644081443634269);
851+
assert_data_eq!(gen_hash(source_id), str!["215644081443634269"].raw());
842852
#[cfg(not(windows))]
843-
assert_eq!(crate::util::hex::short_hash(&source_id), "64bace89c92b101f");
853+
assert_data_eq!(short_hash(&source_id), str!["64bace89c92b101f"].raw());
844854
#[cfg(windows)]
845-
assert_eq!(crate::util::hex::short_hash(&source_id), "01e1e6c391813fb6");
855+
assert_data_eq!(short_hash(&source_id), str!["01e1e6c391813fb6"].raw());
846856

847857
let source_id = SourceId::for_directory(path).unwrap();
848858
#[cfg(not(windows))]
849859
{
850-
assert_eq!(gen_hash(source_id), 6127590343904940368);
851-
assert_eq!(crate::util::hex::short_hash(&source_id), "505191d1f3920955");
860+
assert_data_eq!(gen_hash(source_id), str!["6127590343904940368"].raw());
861+
assert_data_eq!(short_hash(&source_id), str!["505191d1f3920955"].raw());
852862
}
853863
#[cfg(windows)]
854864
{
855-
assert_eq!(gen_hash(source_id), 10423446877655960172);
856-
assert_eq!(crate::util::hex::short_hash(&source_id), "6c8ad69db585a790");
865+
assert_data_eq!(gen_hash(source_id), str!["10423446877655960172"].raw());
866+
assert_data_eq!(short_hash(&source_id), str!["6c8ad69db585a790"].raw());
857867
}
858868
}
859869

0 commit comments

Comments
 (0)