From fe144fc3f64572ab141ed378c53db5cb043cda14 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:36:41 -0500 Subject: [PATCH] Ensure metadata of self-referential crates can be read. (#1035) Also ensure that if reading metadata fails, we don't crash and instead just avoid checking manifest-related lints. --- Cargo.lock | 134 +++++++----------- Cargo.toml | 4 +- src/lib.rs | 13 +- src/snapshot_tests.rs | 23 +++ .../future/Cargo.toml | 7 + .../future/src/lib.rs | 1 + .../new/Cargo.toml | 10 ++ .../new/src/lib.rs | 1 + .../old/Cargo.toml | 7 + .../old/src/lib.rs | 1 + .../query_execution/struct_missing.snap | 14 ++ ...__semver_trick_self_referential-input.snap | 35 +++++ ..._semver_trick_self_referential-output.snap | 32 +++++ 13 files changed, 197 insertions(+), 85 deletions(-) create mode 100644 test_crates/semver_trick_self_referential/future/Cargo.toml create mode 100644 test_crates/semver_trick_self_referential/future/src/lib.rs create mode 100644 test_crates/semver_trick_self_referential/new/Cargo.toml create mode 100644 test_crates/semver_trick_self_referential/new/src/lib.rs create mode 100644 test_crates/semver_trick_self_referential/old/Cargo.toml create mode 100644 test_crates/semver_trick_self_referential/old/src/lib.rs create mode 100644 test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-input.snap create mode 100644 test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-output.snap diff --git a/Cargo.lock b/Cargo.lock index 2d196dab..bc0673ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,8 +337,8 @@ dependencies = [ "atty", "bugreport", "cargo-config2", - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.20.5", "clap", "clap-cargo", "clap-verbosity-flag", @@ -383,6 +383,20 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.6", +] + [[package]] name = "cargo_toml" version = "0.20.5" @@ -393,6 +407,16 @@ dependencies = [ "toml 0.8.19", ] +[[package]] +name = "cargo_toml" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" +dependencies = [ + "serde", + "toml 0.8.19", +] + [[package]] name = "cc" version = "1.2.3" @@ -431,7 +455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2ea69cefa96b848b73ad516ad1d59a195cdf9263087d977f648a818c8b43e" dependencies = [ "anstyle", - "cargo_metadata", + "cargo_metadata 0.18.1", "clap", ] @@ -2692,15 +2716,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustdoc-types" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9be1bc4a0ec3445cfa2e4ba112827544890d43d68b7d1eda5359a9c09d2cd8" -dependencies = [ - "serde", -] - [[package]] name = "rustdoc-types" version = "0.28.1" @@ -2719,15 +2734,6 @@ dependencies = [ "serde", ] -[[package]] -name = "rustdoc-types" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e3124c5a7883153fe3e762da9998cf36c302dbf1cc237869d297f9713e5655" -dependencies = [ - "serde", -] - [[package]] name = "rustdoc-types" version = "0.31.0" @@ -3326,26 +3332,12 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "30.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5cbd647bc404a1c04abcc5ab673a61b7f996da0c3a65bf282e6dffc00fed7d" -dependencies = [ - "cargo_metadata", - "cargo_toml", - "rayon", - "rustc-hash", - "rustdoc-types 0.26.0", - "trustfall", -] - -[[package]] -name = "trustfall-rustdoc-adapter" -version = "32.3.0" +version = "32.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a6d11d915cb39265771c547a0e2d5d446ce26345dfc3d2832f6d4f26f229d" +checksum = "28b25d413a95f20e1c1f7aef9cc4252a9d8dd0593154d4933a7a3f7728815311" dependencies = [ - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.21.0", "rayon", "rustc-hash", "rustdoc-types 0.28.1", @@ -3354,12 +3346,12 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "33.3.0" +version = "33.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9339448bef1aaf543b26acd1aa15d9a979f81e96b7acafae7c189f94f176bdb4" +checksum = "733903d67de08f71488664863d26124745cbc7902e81c97d31d6ae0349729b22" dependencies = [ - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.21.0", "rayon", "rustc-hash", "rustdoc-types 0.29.1", @@ -3368,26 +3360,12 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "34.2.0" +version = "35.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee1cc32494489876a0ab7c242889e79150a0a189e4b1d471993a74ad82ab8a" +checksum = "7afdd45e828aa5af483c5fd0260ca5b679be7b1870f5d97beb002843aeaf791b" dependencies = [ - "cargo_metadata", - "cargo_toml", - "rayon", - "rustc-hash", - "rustdoc-types 0.30.0", - "trustfall", -] - -[[package]] -name = "trustfall-rustdoc-adapter" -version = "35.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "499001e412ad753a1a344d751b5c99f53a3fdeaed2a5b91357174c2b4360470f" -dependencies = [ - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.21.0", "rayon", "rustc-hash", "rustdoc-types 0.31.0", @@ -3396,12 +3374,12 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "36.2.0" +version = "36.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f0d9ea888721de62eac48f7838da7c7f6933e92c4152c5ffd8e785c88574f" +checksum = "b51299db86ed102f08a04001566f4a78192ed5752835c3c066f19ea4cd58a3e1" dependencies = [ - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.21.0", "rayon", "rustc-hash", "rustdoc-types 0.32.2", @@ -3410,12 +3388,12 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "37.0.0" +version = "37.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3881686448ceb86978de52ed8da1989439df3289eda04c841a6fdb7b6f7b7b2" +checksum = "7b2b24ef4e7fd944b6c76531332f5510d4d47a775573215b4f7c64505481f9c4" dependencies = [ - "cargo_metadata", - "cargo_toml", + "cargo_metadata 0.19.1", + "cargo_toml 0.21.0", "rayon", "rustc-hash", "rustdoc-types 0.33.0", @@ -3452,23 +3430,21 @@ dependencies = [ [[package]] name = "trustfall_rustdoc" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5ed08e834dc55a2837376b7093868b4f5dea37972368c2db658f332d1f07e5" +checksum = "482f7f9c4838f6fb4fb64347a3fdd3b70688e63a83e6ae81f481d0e0e36b8d4b" dependencies = [ "anyhow", - "cargo_metadata", + "cargo_metadata 0.19.1", "serde", "serde_json", "thiserror 2.0.6", "trustfall", - "trustfall-rustdoc-adapter 30.3.0", - "trustfall-rustdoc-adapter 32.3.0", - "trustfall-rustdoc-adapter 33.3.0", - "trustfall-rustdoc-adapter 34.2.0", - "trustfall-rustdoc-adapter 35.2.0", - "trustfall-rustdoc-adapter 36.2.0", - "trustfall-rustdoc-adapter 37.0.0", + "trustfall-rustdoc-adapter 32.4.0", + "trustfall-rustdoc-adapter 33.4.0", + "trustfall-rustdoc-adapter 35.3.0", + "trustfall-rustdoc-adapter 36.3.0", + "trustfall-rustdoc-adapter 37.1.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 69103732..54ce0538 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,8 @@ exclude = [".github/", "brand/", "scripts/", "test_crates/", "test_outputs/", "t trustfall = "0.8.0" # `cargo_metadata` is used at the API boundary of `trustfall_rustdoc`, # so ensure the version we use for `cargo_metadata` here matches what `trustfall_rustdoc` uses too. -trustfall_rustdoc = { version = "0.18.1", default-features = false, features = ["v32", "v33", "v35", "v36", "v37", "rayon", "rustc-hash"] } -cargo_metadata = "0.18.1" +trustfall_rustdoc = { version = "0.19.0", default-features = false, features = ["v32", "v33", "v35", "v36", "v37", "rayon", "rustc-hash"] } +cargo_metadata = "0.19.1" # End of dependency block clap = { version = "4.5.21", features = ["derive", "cargo"] } diff --git a/src/lib.rs b/src/lib.rs index 2cb2a458..c13027e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,10 +243,15 @@ impl Scope { /// semver-check rlib, dylib, and staticlib targets as well. fn is_lib_like_checkable_target(target: &cargo_metadata::Target) -> bool { target.is_lib() - || target - .kind - .iter() - .any(|kind| matches!(kind.as_str(), "rlib" | "dylib" | "staticlib")) + || target.kind.iter().any(|kind| { + matches!( + kind, + cargo_metadata::TargetKind::RLib { .. } + | cargo_metadata::TargetKind::DyLib { .. } + | cargo_metadata::TargetKind::CDyLib { .. } + | cargo_metadata::TargetKind::StaticLib { .. } + ) + }) } impl Check { diff --git a/src/snapshot_tests.rs b/src/snapshot_tests.rs index 25a5f370..cb326ebd 100644 --- a/src/snapshot_tests.rs +++ b/src/snapshot_tests.rs @@ -402,6 +402,29 @@ fn multiple_ambiguous_package_name_definitions() { ); } +/// Ensure that linting self-referential packages (usually used for the "SemVer trick") +/// works properly and doesn't suffer any issues due to the self-referential metadata. +/// +/// More info on the "SemVer trick": https://github.com/dtolnay/semver-trick +/// +/// This test currently triggers the `struct_missing` lint as a false-positive, +/// due to the cross-crate re-export. This should be fixed when we start supporting +/// cross-crate items. +#[test] +fn semver_trick_self_referential() { + assert_integration_test( + "semver_trick_self_referential", + &[ + "cargo", + "semver-checks", + "--baseline-root", + "test_crates/semver_trick_self_referential/old/", + "--manifest-path", + "test_crates/semver_trick_self_referential/new/", + ], + ); +} + /// Helper function which lists all files in the directory recursively. /// /// # Arguments diff --git a/test_crates/semver_trick_self_referential/future/Cargo.toml b/test_crates/semver_trick_self_referential/future/Cargo.toml new file mode 100644 index 00000000..d732e95d --- /dev/null +++ b/test_crates/semver_trick_self_referential/future/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "semver_trick_self_referential" +version = "0.2.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/semver_trick_self_referential/future/src/lib.rs b/test_crates/semver_trick_self_referential/future/src/lib.rs new file mode 100644 index 00000000..f6b1a179 --- /dev/null +++ b/test_crates/semver_trick_self_referential/future/src/lib.rs @@ -0,0 +1 @@ +pub struct Example; diff --git a/test_crates/semver_trick_self_referential/new/Cargo.toml b/test_crates/semver_trick_self_referential/new/Cargo.toml new file mode 100644 index 00000000..d2cefe45 --- /dev/null +++ b/test_crates/semver_trick_self_referential/new/Cargo.toml @@ -0,0 +1,10 @@ +[package] +publish = false +name = "semver_trick_self_referential" +version = "0.1.1" +edition = "2021" + +[dependencies] +# The "SemVer trick": reference a future major version of the package, and re-export its types +# within the same *minor* version to offer a smoother upgrade process between major versions. +self_ref = { package = "semver_trick_self_referential", path = "../future", version = "0.2.0" } diff --git a/test_crates/semver_trick_self_referential/new/src/lib.rs b/test_crates/semver_trick_self_referential/new/src/lib.rs new file mode 100644 index 00000000..546105c8 --- /dev/null +++ b/test_crates/semver_trick_self_referential/new/src/lib.rs @@ -0,0 +1 @@ +pub use self_ref::Example; diff --git a/test_crates/semver_trick_self_referential/old/Cargo.toml b/test_crates/semver_trick_self_referential/old/Cargo.toml new file mode 100644 index 00000000..9a4de1cf --- /dev/null +++ b/test_crates/semver_trick_self_referential/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "semver_trick_self_referential" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/semver_trick_self_referential/old/src/lib.rs b/test_crates/semver_trick_self_referential/old/src/lib.rs new file mode 100644 index 00000000..f6b1a179 --- /dev/null +++ b/test_crates/semver_trick_self_referential/old/src/lib.rs @@ -0,0 +1 @@ +pub struct Example; diff --git a/test_outputs/query_execution/struct_missing.snap b/test_outputs/query_execution/struct_missing.snap index d440c911..e04decee 100644 --- a/test_outputs/query_execution/struct_missing.snap +++ b/test_outputs/query_execution/struct_missing.snap @@ -1,6 +1,7 @@ --- source: src/query.rs expression: "&query_execution_results" +snapshot_kind: text --- { "./test_crates/move_item_and_reexport/": [ @@ -73,6 +74,19 @@ expression: "&query_execution_results" "visibility_limit": String("public"), }, ], + "./test_crates/semver_trick_self_referential/": [ + { + "name": String("Example"), + "path": List([ + String("semver_trick_self_referential"), + String("Example"), + ]), + "span_begin_line": Uint64(1), + "span_filename": String("src/lib.rs"), + "struct_type": String("unit"), + "visibility_limit": String("public"), + }, + ], "./test_crates/struct_missing/": [ { "name": String("WillBeRemovedStruct"), diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-input.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-input.snap new file mode 100644 index 00000000..d76bdf2d --- /dev/null +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-input.snap @@ -0,0 +1,35 @@ +--- +source: src/snapshot_tests.rs +expression: check +snapshot_kind: text +--- +Check( + scope: Scope( + mode: DenyList(PackageSelection( + selection: DefaultMembers, + excluded_packages: [], + )), + ), + current: Rustdoc( + source: Root("test_crates/semver_trick_self_referential/new/"), + ), + baseline: Rustdoc( + source: Root("test_crates/semver_trick_self_referential/old/"), + ), + release_type: None, + current_feature_config: FeatureConfig( + features_group: Heuristic, + extra_features: [], + is_baseline: false, + ), + baseline_feature_config: FeatureConfig( + features_group: Heuristic, + extra_features: [], + is_baseline: true, + ), + build_target: None, + witness_generation: WitnessGeneration( + show_hints: false, + witness_directory: None, + ), +) diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-output.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-output.snap new file mode 100644 index 00000000..60c578e5 --- /dev/null +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__semver_trick_self_referential-output.snap @@ -0,0 +1,32 @@ +--- +source: src/snapshot_tests.rs +expression: result +snapshot_kind: text +--- +success: false +--- stdout --- + +--- failure struct_missing: pub struct removed or renamed --- + +Description: +A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely. + ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove + impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/[VERSION]/src/lints/struct_missing.ron + +Failed in: + struct semver_trick_self_referential::Example, previously in file [ROOT]/test_crates/semver_trick_self_referential/old/src/lib.rs:1 + +--- stderr --- + Building semver_trick_self_referential v0.1.1 (current) + Built [TIME] (current) + Parsing semver_trick_self_referential v0.1.1 (current) + Parsed [TIME] (current) + Building semver_trick_self_referential v0.1.0 (baseline) + Built [TIME] (baseline) + Parsing semver_trick_self_referential v0.1.0 (baseline) + Parsed [TIME] (baseline) + Checking semver_trick_self_referential v0.1.0 -> v0.1.1 (minor change) + Checked [TIME] [TOTAL] checks: [PASS] pass, 1 fail, 0 warn, 7 skip + + Summary semver requires new major version: 1 major and 0 minor checks failed + Finished [TIME] semver_trick_self_referential